دورة حياة خدمات موثوقة

الخدمات الموثوقة هي أحد نماذج البرمجة المتوفرة في Azure Service Fabric. عند التعرف على دورة حياة الخدمات الموثوقة، من المهم فهم أحداث دورة الحياة الأساسية. يعتمد الترتيب الدقيق للأحداث على تفاصيل التكوين.

بشكل عام، تتضمن دورة حياة الخدمات الموثوقة الأحداث التالية:

  • أثناء بدء التشغيل:
    • يتم بناء الخدمات.
    • تحتوي الخدمات على فرصة لبناء وإرجاع صفر أو أكثر من المستمعين.
    • يتم فتح أي مستمعين عادوا للتواصل مع الخدمة.
    • تم استدعاء طريقة الخدمة runAsync، لذا يمكن للخدمة القيام بعمل طويل المدى أو في الخلفية.
  • أثناء الإغلاق:
    • تم إلغاء رمز الإلغاء الذي تم تمريره إلى runAsync، ويتم إغلاق المستمعين.
    • تم إتلاف كائن الخدمة نفسه.

قد يتغير ترتيب الأحداث في خدمات Reliable بشكل طفيف اعتمادًا على ما إذا كانت الخدمة الموثوقة عديمة الحالة أو ذات حالة.

أيضًا، بالنسبة للخدمات ذات الحالة الخاصة، يجب عليك معالجة سيناريو المبادلة الأساسي. أثناء هذا التسلسل، يتم نقل دور الأساسي إلى نسخة متماثلة أخرى (أو يعود) دون إيقاف تشغيل الخدمة.

أخيرًا، عليك التفكير في ظروف الخطأ أو الفشل.

بدء تشغيل خدمة Stateless

دورة حياة الخدمة عديمة الحالة واضحة إلى حد ما. إليك ترتيب الأحداث:

  1. تم إنشاء الخدمة.
  2. يتم استدعاء StatelessService.createServiceInstanceListeners()، ويتم فتح أي مستمعين مرتدين. CommunicationListener.openAsync() يتم استدعاؤه على كل وحدة استماع.
  3. ثم بالتوازي مع ذلك:
    • تم استدعاء طريقة runAsync الخدمة (StatelessService.runAsync()).
    • إذا كان موجودًا، فسيتم استدعاء طريقة onOpenAsync الخاصة بالخدمة. على وجه التحديد، تم استدعاء StatelessService.onOpenAsync(). هذا تجاوز غير شائع، لكنه متاح.

إيقاف تشغيل الخدمة عديمة الحالة.

عند إيقاف تشغيل خدمة Stateless، يتم اتباع نفس النمط، ولكن في الاتجاه المعاكس:

  1. يتم إغلاق أي وحدات استماع مفتوحين. CommunicationListener.closeAsync() يتم استدعاؤه على كل مستمع.
  2. تم إلغاء رمز الإلغاء الذي تم تمريره إلى runAsync(). التحقق من إرجاع خاصية isCancelled رمز الإلغاء true، وإذا تم استدعاؤها، فإن طريقة throwIfCancellationRequested الرمز المميز تلقي CancellationException.
  3. عند انتهاء runAsync()، يتم استدعاء أسلوب الخدمة StatelessService.onCloseAsync()، إذا كانت موجودة. مرة أخرى، هذا ليس تجاوزًا شائعًا، ولكن يمكن استخدامه لإغلاق الموارد بأمان أو إيقاف معالجة الخلفية أو إنهاء حفظ الحالة الخارجية أو إغلاق الاتصالات الحالية.
  4. بعد انتهاء StatelessService.onCloseAsync()، يتم إتلاف كائن الخدمة.

بدء تشغيل خدمة Stateful

الخدمات ذات الحالة الخاصة لها نمط مشابه للخدمات stateless، مع بعض التغييرات. إليك ترتيب الأحداث لبدء خدمة ذات حالة:

  1. جرى إنشاء الخدمة.
  2. StatefulServiceBase.onOpenAsync() التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.
  3. StatefulServiceBase.createServiceReplicaListeners() يتم الاستناد إليها.
    • إذا كانت الخدمة خدمة أساسية، يتم فتح جميع المستمعين الذين تم إرجاعهم. يتم استدعاء CommunicationListener.openAsync() على كل مستمع.
    • إذا كانت الخدمة خدمة ثانوية، فلن يتم فتح سوى المستمعين المحددين كـ listenOnSecondary = true. وجود وحدات استماع مفتوحة على المرتبات الثانوية أقل شيوعا.
  4. ثم بالتوازي مع ذلك:
    • إذا كانت الخدمة حاليًّا أساسية، فسيتم استدعاء طريقة الخدمة StatefulServiceBase.runAsync().
    • StatefulServiceBase.onChangeRoleAsync() التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

ملاحظة

للحصول على نسخة ثانوية متماثلة جديدة، StatefulServiceBase.onChangeRoleAsync() تستدعى مرتين. مرة واحدة بعد الخطوة 2، عندما تصبح ثانوية خاملة ومرة أخرى خلال الخطوة 4، عندما تصبح ثانوية نشطة. لمزيد من المعلومات حول النسخة المتماثلة ودورة حياة المثيل، اقرأ النسخ المتماثلة ودورة حياة المثيل.

إيقاف تشغيل الخدمة ذات الحالة.

مثل الخدمات عديمة الحالة، تكون أحداث دورة الحياة أثناء إيقاف التشغيل هي نفسها أثناء بدء التشغيل ، ولكن يتم عكسها. عند إيقاف تشغيل خدمة حالة، تحدث الأحداث التالية:

  1. يتم إغلاق أي وحدات استماع مفتوحين. CommunicationListener.closeAsync() يتم استدعاؤه على كل مستمع.
  2. تم إلغاء رمز الإلغاء الذي تم تمريره إلى runAsync(). يؤدي استدعاء طريقة isCancelled() رمز الإلغاء إلى إرجاع true، وإذا تم استدعاؤه، فإن طريقة throwIfCancellationRequested() الرمز المميز تلقي OperationCanceledException. تنتظر خدمة Service Fabric لحين اكتمال runAsync().

ملاحظة

الانتظار حتى runAsync الانتهاء ضروري فقط إذا كانت هذه النسخة المتماثلة نسخة متماثلة أساسية.

  1. بعد انتهاء runAsync()، يتم استدعاء أسلوب الخدمة StatefulServiceBase.onCloseAsync(). تُعد هذه المكالمة تجاوز غير شائع، ولكنها متوفرة.
  2. بعد انتهاء StatefulServiceBase.onCloseAsync()، يتم إتلاف كائن الخدمة.

المقايضات الأولية لخدمة Stateful

أثناء تشغيل خدمة stateful، يتم فتح مستمعي الاتصال ويتم استدعاء الأسلوب runAsync فقط للنسخ المتماثلة الأولية لتلك الخدمات ذات الحالة. يتم إنشاء النسخ المتماثلة الثانوية، ولكن لا ترى أي مكالمات أخرى. أثناء تشغيل الخدمة stateful الخاصة، يمكن أن تتغير النسخة المتماثلة الأساسية حاليًّا. تعتمد أحداث دورة الحياة التي يمكن للنسخة المتماثلة ذات الحالة أن تراها على ما إذا كانت النسخة المتماثلة يتم تخفيضها أو ترقيتها أثناء المبادلة.

للمرحلة الابتدائية التي تم تخفيضها

تحتاج Service Fabric إلى النسخة المتماثلة الأساسية التي تم تخفيضها لإيقاف معالجة الرسائل وإيقاف أي عمل في الخلفية. تشبه هذه الخطوة وقت إيقاف تشغيل الخدمة. أحد الاختلافات هو أن الخدمة لم يتم إتلافها أو إغلاقها، لأنها تظل ثانوية. تحدث الأحداث التالية:

  1. يتم إغلاق أي وحدات استماع مفتوحين. CommunicationListener.closeAsync() يتم استدعاؤه على كل مستمع.
  2. تم إلغاء رمز الإلغاء الذي تم تمريره إلى runAsync(). يؤدي التحقق من طريقة isCancelled() رمز الإلغاء إلى إرجاع true. إذا تم الاستدعاء، فإن طريقة throwIfCancellationRequested() الرمز المميز تطرح OperationCanceledException. تنتظر خدمة Service Fabric لحين اكتمال runAsync().
  3. يتم فتح وحدات الاستماع الموسومة بعلامة listenOnSecondary = true.
  4. يتم استدعاء الخدمة StatefulServiceBase.onChangeRoleAsync(). عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

للترقية الثانوية

وبالمثل، تحتاج Service Fabric إلى النسخة المتماثلة الثانوية التي يتم ترقيتها لبدء الاستماع للرسائل الموجودة على السلك، وبدء أي مهام في الخلفية تحتاج إلى إكمالها. تشبه هذه العملية وقت إنشاء الخدمة. الفرق هو أن النسخة المتماثلة نفسها موجودة بالفعل. تحدث الأحداث التالية:

  1. تُستدعى CommunicationListener.closeAsync() لجميع وحدات الاستماع المفتوحة (الموسومة بعلامة listenOnSecondary = true)
  2. يتم فتح جميع وحدات الاستماع للاتصالات. CommunicationListener.openAsync() يتم استدعاؤه على كل وحدة استماع.
  3. ثم بالتوازي مع ذلك:
    • يتم استدعاء طريقة الخدمة StatefulServiceBase.runAsync() .
    • StatefulServiceBase.onChangeRoleAsync() التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

ملاحظة

يستدعى createServiceReplicaListeners مرة واحدة فقط ولا يتم استدعاؤه مرة أخرى أثناء عملية ترقية النسخة المتماثلة أو إعادتها للحالة السابقة؛ يستخدم نفس المثيلات ServiceReplicaListener ولكن يتم إنشاء مثيلات جديدة CommunicationListener (عن طريق استدعاء الأسلوب ServiceReplicaListener.createCommunicationListener) بعد إغلاق المثيلات السابقة.

المشكلات الشائعة أثناء إيقاف تشغيل الخدمة المصحوب بالحالة وتخفيض الترتيب الأساسي

يغير تصميم الخدمة الأساسي للخدمة ذات الحالة الخاصة لأسباب متعددة. الأسباب الأكثر شيوعًا هي إعادة توازن المجموعة و ترقية التطبيق . أثناء هذه العمليات، من المهم أن تحترم الخدمة cancellationToken. ينطبق هذا أيضًا أثناء إيقاف الخدمة العادي، مثل إذا تم حذف الخدمة.

يمكن أن تواجه الخدمات التي لا تتعامل مع الإلغاء بشكل سليم العديد من المشكلات. هذه العمليات بطيئة لأن نسيج الخدمة ينتظر توقف الخدمات بأمان. يمكن أن يؤدي هذا في النهاية إلى ترقيات فاشلة تنتهي مهلتها وتتراجع. يمكن أن يؤدي عدم احترام رمز الإلغاء أيضًا إلى حدوث مجموعات غير متوازنة. تصبح المجموعات غير متوازنة لأن العقد تصبح ساخنة. ومع ذلك، لا يمكن إعادة موازنة الخدمات لأن الأمر يستغرق وقتًا طويلًا لنقلها إلى مكان آخر.

نظرًا لأن الخدمات stateful، فمن المحتمل أيضًا أن تستخدم الخدمات مجموعات موثوقة . في تصميم الخدمة، عندما يتم تخفيض رتبة الأساسي، فإن أحد الأشياء الأولى التي تحدث هو إبطال حق الوصول للكتابة إلى الحالة الأساسية. يؤدي هذا إلى مجموعة ثانية من المشكلات التي قد تؤثر على دورة حياة الخدمة. تُرجع المجموعات الاستثناءات بناءً على التوقيت وما إذا كان يتم نقل النسخة المتماثلة أو إيقاف تشغيلها. من المهم التعامل مع هذه الاستثناءات على نحو صحيح.

الاستثناءات التي يقدمها نسيج الخدمة هي إما دائمة (FabricException) أو عابرة (FabricTransientException) . يجب تسجيل الاستثناءات الدائمة وإلقاؤها. يمكن إعادة محاولة الاستثناءات المؤقتة بناءً على منطق إعادة المحاولة.

جزء مهم من اختبار الخدمات Reliable والتحقق منها هو معالجة الاستثناءات التي تأتي من استخدام ReliableCollections بالتزامن مع أحداث دورة حياة الخدمة. نوصي دائمًا بتشغيل خدمتك تحت الحمل. يجب أيضًا إجراء الترقيات و اختبار الفوضى قبل النشر في الإنتاج. تساعد هذه الخطوات الأساسية في ضمان تنفيذ خدمتك بشكل صحيح، وأنها تتعامل مع أحداث دورة الحياة بشكل صحيح.

ملاحظات حول دورة حياة الخدمة

  • تعد كل من طريقة runAsync() واستدعاءات createServiceInstanceListeners/createServiceReplicaListeners اختياريين. قد تحتوي الخدمة على أحدهما أو كليهما أو لا يوجد أي منهما. على سبيل المثال، إذا كانت الخدمة تقوم بجميع أعمالها استجابةً لمكالمات المستخدم، فلا داعي لتطبيق runAsync(). فقط المستمعون للاتصالات والكود المرتبط بهم ضروريون. وبالمثل، فإن إنشاء مستمعين للتواصل وإعادتهم أمر اختياري. قد يكون للخدمة عمل في الخلفية فقط لتقوم به، لذلك تحتاج فقط إلى تنفيذrunAsync().
  • إنه صالح لخدمة ما لإكمال runAsync() بنجاح والعودة منه. لا يعتبر هذا حالة فشل. إنه يمثل خلفية العمل لإنهاء الخدمة. بالنسبة إلى الخدمات stateful Reliable، سيتم استدعاء runAsync() مرة أخرى إذا تم تخفيض رتبة الخدمة من أساسية، ثم ترقيتها مرة أخرى إلى أساسية.
  • إذا خرجت خدمة من runAsync() عن طريق طرح استثناء غير متوقع، فهذا يعد إخفاقًا. تم إغلاق كائن الخدمة، والإبلاغ عن خطأ صحي.
  • على الرغم من عدم وجود حد زمني للعودة من هذه الأساليب، فإنك تفقد القدرة على الكتابة على الفور. لذلك، لا يمكنك إكمال أي عمل حقيقي. نوصيك بالعودة في أسرع وقت ممكن عند تلقي طلب الإلغاء. إذا لم تستجب خدمتك لاستدعاءات واجهة برمجة التطبيقات للنظام هذه في فترة زمنية معقولة، فقد تنهي خدمة النسيج الخدمة قسراً. عادة، يحدث هذا فقط أثناء ترقيات التطبيق أو عند حذف خدمة. هذه المهلة هي 15 دقيقة بشكل افتراضي.
  • تؤدي حالات الفشل في مسار onCloseAsync() إلى استدعاء onAbort(). هذه المكالمة هي فرصة أخيرة وأفضل جهد للخدمة لتنظيف وإطلاق أي موارد طالبت بها. يتم استدعاء هذا بشكل عام عند اكتشاف خطأ دائم في العقدة، أو عندما يتعذر على تصميم الخدمة إدارة دورة حياة مثيل الخدمة بشكل موثوق بسبب الأعطال الداخلية.
  • OnChangeRoleAsync() يتم استدعاؤه عندما تقوم النسخة المتماثلة الخاصة بالخدمة ذات الحالة بتغيير الدور، على سبيل المثال إلى أساسي أو ثانوي. يتم إعطاء النسخ المتماثلة الأساسية ميزة حالة الكتابة (يسمح لها بإنشاء وكتابة مجموعات موثوقة). يتم منح النسخ المتماثلة الثانوية ميزة حالة قراءة (يمكن قراءتها فقط من المجموعات الموثوقة الموجودة). يتم تنفيذ معظم العمل في خدمة الحالة بأسلوب النسخة المتماثلة الأساسية. يمكن للنسخ المتماثلة الثانوية إجراء التحقق من صحة القراءة فقط أو إنشاء التقارير أو استخراج البيانات أو مهام أخرى للقراءة فقط.

الخطوات التالية