نظرة عامة بشأن دورة الحياة المتعلقة بالخدمات الموثوق بها

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

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

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

بدء عملية تشغيل الخدمة عديمة الحالة.

دورة حياة الخاص بالخدمة عديمة الحالة واضح. ما يلي هو ترتيب الأحداث:

  1. تم إنشاء الخدمة.
  2. StatelessService.CreateServiceInstanceListeners() يتم استدعاؤه ويتم فتح أي مستمعين تم إرجاعهم. ICommunicationListener.OpenAsync() يتم استدعاؤه على كل وحدة استماع.
  3. بعد ذلك، يحدث شيئان بالتوازي -
    • يتم استدعاء أسلوب الخدمة StatelessService.RunAsync() .
    • إذا كانت موجودة، يتم استدعاء أسلوب الخدمة StatelessService.OnOpenAsync() . تُعد هذه المكالمة تجاوز غير شائع، ولكنها متوفرة. يمكن بدء مهام تهيئة الخدمة القابلة للتوسيع في الوقت الحالي.

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

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

  1. يتم إغلاق أي وحدات استماع مفتوحين. ICommunicationListener.CloseAsync() يتم استدعاؤه على كل وحدة استماع.
  2. يتم إلغاء رمز الإلغاء المميز الذي تم تمريره RunAsync() إليه. يؤدي التحقق من خاصية رمز الإلغاء المميز IsCancellationRequested إلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميز ThrowIfCancellationRequestedيتم التخلص منه OperationCanceledException. تنتظر خدمة Service Fabric لحين اكتمال RunAsync().
  3. بعد انتهاء RunAsync()، يتم استدعاء أسلوب الخدمة StatelessService.OnCloseAsync() إن وجد. يتم استدعاء OnCloseAsync عند إيقاف تشغيل مثيل الخدمة عديم الحالة بأمان. يمكن أن يحدث هذا عند ترقية التعليمات البرمجية للخدمة أو نقل مثيل الخدمة بسبب موازنة التحميل أو اكتشاف خطأ انتقالي. من غير الشائع التجاوز StatelessService.OnCloseAsync()، ولكن يمكن استخدامه من أجل إغلاق الموارد بأمان أو إيقاف عملية معالجة الخلفية أو إنهاء حفظ الحالة الخارجية أو إغلاق الاتصالات الموجودة.
  4. بعد انتهاءStatelessService.OnCloseAsync()، يجب تدمير عنصر الخدمة.

بدء تشغيل الخدمة ذات الحالة

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

  1. تم إنشاء الخدمة.

  2. StatefulServiceBase.OnOpenAsync() التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

  3. StatefulServiceBase.CreateServiceReplicaListeners() يتم الاستناد إليها.

    • إذا كانت الخدمة خدمة أساسية، يجب فتح كافة وحدات الاستماع الذين تم إرجاعهم. ICommunicationListener.OpenAsync() يتم استدعاؤه على كل وحدة استماع.
    • إذا كانت الخدمة خدمة ثانوية، فلن يتم فتح سوى وحدات الاستماع الذين تم وضع علامة ListenOnSecondary = trueعليهم. وجود وحدات استماع مفتوحة على المرتبات الثانوية أقل شيوعا.
  4. ثم بالتوازي مع ذلك:

    • إذا كانت الخدمة الحالية أساسية، يجب استدعاء أسلوب الخدمة StatefulServiceBase.RunAsync() .
    • StatefulServiceBase.OnChangeRoleAsync() التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

    ملاحظة

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

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

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

  1. يتم إغلاق أي وحدات استماع مفتوحين. ICommunicationListener.CloseAsync() يتم استدعاؤه على كل مستمع.

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

  3. يتم إلغاء رمز الإلغاء المميز الذي تم تمريره RunAsync() إليه. يؤدي التحقق من خاصية رمز الإلغاء المميز IsCancellationRequested إلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميز ThrowIfCancellationRequestedيتم التخلص منه OperationCanceledException. تنتظر خدمة Service Fabric لحين اكتمال RunAsync().

    ملاحظة

    تُعتبر الحاجة إلى الانتظار حتى ينتهي RunAsync أمر ضروري فقط إذا كانت هذه النسخة المتماثلة نسخة متماثلة أساسية.

  4. بعد انتهاءStatefulServiceBase.RunAsync()، يجب تدمير عنصر الخدمة.

المبادلات الأساسية للخدمات ذات الحالة

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

بالنسبة للمرحلة الأساسية التي تم تخفيض رتبتها

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

  1. يتم إغلاق أي وحدات استماع مفتوحين. ICommunicationListener.CloseAsync() يتم استدعاؤه على كل وحدة استماع.
  2. يتم إلغاء رمز الإلغاء المميز الذي تم تمريره RunAsync() إليه. يؤدي التحقق من خاصية رمز الإلغاء المميز IsCancellationRequested إلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميز ThrowIfCancellationRequestedيتم التخلص منه OperationCanceledException. تنتظر خدمة Service Fabric لحين اكتمال RunAsync().
  3. يتم فتح وحدات الاستماع الموسومة بعلامة listenOnSecondary = true.
  4. يتم استدعاء الخدمة StatefulServiceBase.OnChangeRoleAsync(). عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.

بالنسبة بالمرحلة الثانوية التي تمت ترقيتها

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

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

ملاحظة

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

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

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

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

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

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

ملاحظات بشأن دورة حياة الخدمة

  • كل من RunAsync() الأسلوب والمكالمات CreateServiceReplicaListeners/CreateServiceInstanceListeners اختيارية. يمكن أن تشمل الخدمة على واحدة منهم، كلاهما ، أو لا. على سبيل المثال، إذا كانت الخدمة تقوم بكل مهامها استجابة لمكالمات المستخدم، فليست هناك حاجة لإجراء عملية تنفيذها RunAsync(). فقط وحدات استماع الاتصالات والتعليمات البرمجية المرتبطة بهم ضرورية. وبالمثل، فإن إنشاء وحدات استماع الاتصال وإعادتهم أمر اختياري، حيث يمكن أن يكون للخدمة عمل أساسي فقط للقيام به، وبالتالي تحتاج فقط إلى التنفيذ RunAsync().
  • حيث أنها صالحة لإكمال الخدمة RunAsync() بنجاح والاسترجاع. لا يُعد الإكمال شرطا للفشل. يشير الإكمال RunAsync() إلى انتهاء العمل الأساسي الخاص بالخدمة. بالنسبة للخدمات الموثوقة ذات الحالة، RunAsync() يتم استدعاؤها مرة أخرى إذا تم تخفيض رتبة النسخة المتماثلة من الأساسية إلى الثانوية ثم ترقيتها مرة أخرى إلى أساسية.
  • إذا خرجت خدمة من RunAsync() عن طريق التخلص من بعض الاستثناءات غير المتوقعة، فهذا يشكل فشلا. يتم إيقاف تشغيل عنصر الخدمة ويتم الإبلاغ عن خطأ صحي.
  • على الرغم من عدم وجود حد زمني لاسترجاع هذه الأساليب، إلا أنك تفقد على الفور القدرة على الكتابة المتعلقة بمجموعات موثوقة، وبالتالي لا يمكنك إكمال أي عمل حقيقي. نوصي بالمواصلة في أسرع وقت ممكن عند استلام طلب الإلغاء. إذا لم تستجب خدمتك لمكالمات واجهة برمجة التطبيقات هذه في فترة زمنية معقولة، فيمكن لتصميم الخدمة إنهاء خدمتك قسراً. عادة ما يحدث هذا فقط أثناء ترقيات التطبيق أو عند القيام بحذف خدمة. مدة المهلة هي 15 دقيقة بشكل افتراضي.
  • تؤدي حالات الإخفاق في المسار OnCloseAsync() إلى استدعاء OnAbort()، وهي فرصة أخيرة لفرصة بذل أفضل مجهود للخدمة للتنظيف والإفراج عن أي موارد طالبوا بملكيتها. يتم استدعاء هذا بشكل عام عند اكتشاف خطأ دائم في العقدة، أو عندما يتعذر على تصميم الخدمة إدارة دورة حياة مثيل الخدمة بشكل موثوق بسبب الأعطال الداخلية.
  • OnChangeRoleAsync() يتم استدعاؤه عندما تقوم النسخة المتماثلة الخاصة بالخدمة ذات الحالة بتغيير الدور، على سبيل المثال إلى أساسي أو ثانوي. يتم إعطاء النسخ المتماثلة الأساسية ميزة حالة الكتابة (يسمح لها بإنشاء وكتابة مجموعات موثوقة). يتم منح النسخ المتماثلة الثانوية ميزة حالة قراءة (يمكن قراءتها فقط من المجموعات الموثوقة الموجودة). يتم تنفيذ معظم العمل في خدمة الحالة بأسلوب النسخة المتماثلة الأساسية. يمكن للنسخ المتماثلة الثانوية إجراء التحقق من صحة القراءة فقط أو إنشاء التقارير أو استخراج البيانات أو مهام أخرى للقراءة فقط.

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