استراتيجيات النشر والتسليم التدريجي

أعلام الميزات (Feature Flags)

18 دقيقة الدرس 5 من 28

أعلام الميزات (Feature Flags)

علم الميزة (أو مفتاح الميزة، أو تبديل الميزة) هو فرع شرطي في الكود يُوجِّه تنفيذ البرنامج بناءً على قيمة تهيئة في وقت التشغيل، لا على عملية نشر جديدة. يمكن تشغيل العلم أو إيقافه دون شحن كود جديد. هذا يفصل بين النشر — دفع الكود الجديد إلى الخوادم — والإصدار — تفعيل ذلك الكود للمستخدمين. وهو اللبنة الأساسية التي تجعل كل تقنية من تقنيات التسليم التدريجي عملية على نطاق واسع.

لماذا تعتمد كبرى الشركات التقنية على الأعلام

في شركات مثل Google وNetflix وFacebook وShopify، تدمج الفِرق تغييراتها إلى الفرع الرئيسي وتنشر إلى الإنتاج عشرات المرات يومياً. يُشحن كود الميزة نصف المكتملة وراء علم قيمته false للجميع. حين تكتمل الميزة، يُفعَّل العلم — أولاً للموظفين الداخليين، ثم لـ 1% من حجم حركة المرور، ثم يتوسع تدريجياً. إذا تراجعت المقاييس، يُعطَّل العلم في ثوانٍ دون الحاجة إلى تراجع كامل عن النشر. يُزيل هذا الأسلوب التشابك بين سرعة الكود والمخاطرة على المنتج.

أنواع الأعلام

  • أعلام الإصدار — إخفاء الأعمال غير المكتملة في الإنتاج؛ تُزال بعد اكتمال شحن الميزة.
  • أعلام التجربة (A/B) — توجيه مجموعات من المستخدمين نحو نسخ متعددة للقياس الإحصائي؛ تُزال بعد إعلان الفائز.
  • أعلام العمليات (مفاتيح الإيقاف الطارئ) — تعطيل نظام فرعي مكلف أو معطوب تحت الضغط دون نشر جديد.
  • أعلام الأذونات — تفعيل ميزات لمستويات معينة من المستخدمين أو مجموعات تجريبية بصفة دائمة.
قاعدة عملية: أعلام الإصدار والتجربة هي أعلام قصيرة العمر (أيام إلى أسابيع). أعلام العمليات والأذونات قد تكون طويلة العمر. عامِلهما بشكل مختلف: يجب أن يكون لكل علم قصير العمر تاريخ إزالة مجدوَل مكتوب في التذكرة يوم إنشائه.

تشريح عملية تقييم العلم

تتبع كل عملية تقييم للعلم نفس مسار الأنابيب: تستقبل SDK مفتاح العلم وسياق التقييم (معرّف المستخدم، البلد، الخطة، الجهاز)، ثم تُقيِّم قواعد الاستهداف بالترتيب وتُعيد نسخة. التقييم متزامن وداخل العملية — لا يوجد استدعاء شبكي خلال معالجة الطلب — لأن SDK تحتفظ بنسخة محلية مؤقتة من مجموعة قواعد العلم.

Feature flag evaluation pipeline Request user, country SDK Local ruleset cache Targeting eval Targeting Rules 1. Beta users → ON 2. 10% rollout 3. Default → OFF Variant true / false / string Flag Delivery Network / Relay Proxy
مسار تقييم علم الميزة: تستخدم SDK مجموعة قواعد مخزنة محلياً — لا استدعاء شبكي على المسار الساخن.

الاستهداف وتقسيم المستخدمين

تتيح قواعد الاستهداف التحكم في من يرى العلم وبأي نسبة. تُقيَّم القواعد من الأعلى للأسفل؛ تسود أول مطابقة:

  1. الاستهداف الفردي — معرّفات مستخدمين محددة (الفريق الداخلي، مهندسو ضمان الجودة).
  2. قواعد السماتcountry == "US"، أو plan == "enterprise"، أو version >= "2.0".
  3. النشر التدريجي بالنسبة المئوية — تقسيم حتمي بناءً على دالة تجزئة لـ userId + flagKey حتى يقع المستخدم دائماً في نفس المجموعة.
  4. القاعدة الافتراضية — الاحتياط لكل من لم تنطبق عليه القواعد السابقة.
أهمية الثبات في التقسيم. إذا استخدمت رقماً عشوائياً في كل طلب، سيرى المستخدم الميزة تظهر وتختفي بين تحميلات الصفحة. استخدم دائماً دالة تجزئة على userId + flagKey + salt لضمان تجربة مستخدم متسقة.

تطبيق مفتاح إيقاف طارئ مع OpenFeature

OpenFeature هو معيار SDK صادر عن CNCF يفصل التطبيق عن مزوّد الأعلام (LaunchDarkly أو Flagsmith أو Unleash أو مزوّد مخصص). يتيح هذا استبدال المزوّد دون إعادة كتابة كود التطبيق.

# تثبيت Go SDK لـ OpenFeature مع مزوّد Flagsmith go get github.com/open-feature/go-sdk go get github.com/open-feature/go-sdk-contrib/providers/flagsmith # main.go — تهيئة المزوّد مرة واحدة عند بدء التشغيل import ( "github.com/open-feature/go-sdk/pkg/openfeature" flagsmithProvider "github.com/open-feature/go-sdk-contrib/providers/flagsmith/pkg" ) provider := flagsmithProvider.NewProvider(flagsmithProvider.Config{ SDKKey: os.Getenv("FLAGSMITH_SERVER_KEY"), EnablePolling: true, PollingInterval: 30 * time.Second, // تحديث مجموعة القواعد كل 30 ثانية }) openfeature.SetProvider(provider) client := openfeature.NewClient("checkout-service") # داخل معالج الطلب — تقييم مفتاح الإيقاف الطارئ enabled, err := client.BooleanValue( ctx, "checkout.new-payment-flow", // مفتاح العلم false, // القيمة الآمنة الافتراضية عند خطأ SDK openfeature.NewEvaluationContext("user-"+userID, map[string]interface{}{ "plan": user.Plan, "country": user.Country, }), ) if enabled { return newPaymentFlow(ctx, order) } return legacyPaymentFlow(ctx, order)

القيمة الافتراضية false حاسمة. إذا كانت خدمة الأعلام غير متاحة، تُعيد SDK القيمة الافتراضية — التي يجب أن تكون دائماً المسار الآمن والمختبر. لا تضع القيمة الافتراضية true لميزة غير مختبرة.

نظافة الأعلام والديون التقنية

تتراكم الأعلام. قاعدة كود تحتوي على 200 علم متقادم تعاني من انفجار تركيبي في مساحة الاختبار. في الواقع العملي هذا يُسبب حوادث حقيقية — كان انقطاع خدمة Salesforce عام 2021 مرتبطاً جزئياً بتفاعل مجموعة غير مختبرة من الأعلام القديمة. ديون الأعلام خطيرة بنفس خطورة الديون البرمجية.

طبِّق هذه الممارسات في كل فريق:

  • المالك + تاريخ الانتهاء عند الإنشاء — يجب أن يكون لكل علم فريق مالك وتاريخ remove_by في بيانات العلم. احظر دمج PRs التي تضيف علماً دون هذين الحقلين.
  • وسم الأعلام في الكود — أضف تعليقاً // TODO: remove flag "checkout.new-payment-flow" by 2025-09-01 @payments-team بجوار كل تقييم علم.
  • تتبع تقييمات الأعلام — أرسل أحداث التقييم إلى منصة الرصد. إذا لم يُقيَّم علم منذ 30 يوماً، فهو مرشح للإزالة.
  • تنبيه الأعلام المتروكة — يجب أن تُبرز لوحة إدارة الأعلام الأعلام التي لم تُقيَّم منذ 14 يوماً. معظم منصات SaaS (LaunchDarkly، Unleash) تدعم هذا بشكل أصلي.
خطأ إنتاجي شائع — أعلام دائمة في مستودع مشترك. حين يُصنِّف فريق علم إذن باعتباره "دائماً" لتجنب مهمة التنظيف، يفترض المهندسون الجدد أن جميع الأعلام دائمة. خلال 18 شهراً ستجد 400 علم بلا أصحاب ولا تواريخ إزالة. ألزِم بحذف الكود لكل علم يصل إلى نسبة 100% دون قواعد استهداف — يجب حذف مسار الكود القديم، لا مجرد ترك فرع ميت.

استضافة الأعلام ذاتياً مقابل SaaS

في الصناعات الخاضعة للتنظيم أو البيئات المعزولة عن الإنترنت، تُعد حلول الاستضافة الذاتية مثل Unleash (مفتوح المصدر، MIT) أو Flagsmith (مفتوح المصدر، AGPL) جاهزة للإنتاج. انشر Relay Proxy في كل منطقة لضمان تقييم العلم في أقل من ميلي ثانية حتى إذا كان الخادم المركزي غير متاح.

# نشر Unleash بالاستضافة الذاتية عبر Docker Compose (نمط إنتاجي) # مقتطف docker-compose.yml services: unleash: image: unleashorg/unleash-server:6 environment: DATABASE_URL: "postgres://unleash:${DB_PASSWORD}@db:5432/unleash" UNLEASH_URL: "https://flags.internal.example.com" AUTH_TYPE: "custom" # ربط نظام SSO الخاص بك هنا INIT_ADMIN_API_TOKENS: "${ADMIN_TOKEN}" ports: - "4242:4242" depends_on: db: condition: service_healthy db: image: postgres:16-alpine environment: POSTGRES_USER: unleash POSTGRES_PASSWORD: "${DB_PASSWORD}" POSTGRES_DB: unleash healthcheck: test: ["CMD-SHELL", "pg_isready -U unleash"] interval: 5s retries: 5 unleash-proxy: image: unleashorg/unleash-proxy:1 environment: UNLEASH_URL: "http://unleash:4242/api/" UNLEASH_API_TOKEN: "${PROXY_TOKEN}" UNLEASH_PROXY_SECRETS: "${CLIENT_SECRET}" ports: - "3000:3000"

الأعلام وتكامل CI/CD

عامِل تغييرات الأعلام كعمليات نشر. حين تقلب علماً من 0% إلى 10% عبر واجهة المستخدم، يجب أن يتدفق حدث التدقيق إلى نظام إدارة التغييرات (PagerDuty، Jira، ServiceNow). اربط webhook منصة الأعلام بأداة إدارة الحوادث حتى يرى مهندس الاستجابة تغيير العلم مبرزاً في جدول أحداث الحادثة إذا اندلع تنبيه SLO خلال خمس دقائق من تغيير العلم. هذا يُقلل بشكل كبير من متوسط وقت الاسترداد (MTTR).

GitOps للأعلام. خزِّن تعريفات الأعلام كملفات YAML في مستودع Git وطبِّقها عبر CI. يمنحك هذا مراجعة PR لتغييرات الأعلام، والتراجع التلقائي عبر git revert، وسجل تدقيق قائم على الفروق — تماماً كما تحصل عليه مع مانيفستات Kubernetes عبر ArgoCD. كل من Flagsmith وUnleash يدعمان الاستيراد والتصدير بنهج التهيئة-كـ-كود.