نظرة عامة بشأن دورة الحياة المتعلقة بالخدمات الموثوق بها
عندما تفكر في دورات الحياة المتعلقة بخدمات تصميم الخدمة الموثوقة الخاصة بـ Azure، فإن أساسيات دورة الحياة هي الأكثر أهمية. بشكل عام، تشمل دورة الحياة ما يلي:
- أثناء بدء عملية التشغيل:
- يتم تكوين الخدمات.
- تمتلك الخدمات فرصة لبناء واسترداد صفر أو أكثر من وحدات الاستماع.
- يتم فتح أي وحدات استماع مرتجعة، مما يسمح بالتواصل مع الخدمة.
- يتم استدعاء أسلوبRunAsync الخاصة بالخدمة، مما يسمح للخدمة بالقيام بمهام طويلة الأمد أو مهمة في الخلفية.
- أثناء عملية الإغلاق:
- يتعين إلغاء الرمز المميز للإلغاء الذي تم تمريره إلى RunAsync، وإغلاق وحدات الاستماع.
- بعد إغلاق وحدات الاستماع، يتم تدمير عنصر الخدمة نفسه.
يوجد تفاصيل بشأن الترتيب الدقيق لهذه الأحداث. يمكن أن يتغير ترتيب الأحداث قليلا اعتمادا على ما إذا كانت الخدمة الموثوقة عديمة الحالة أو مهمة. بالإضافة إلى ذلك، بالنسبة للخدمات المهمة، يجب علينا التعامل مع سيناريو المبادلة الأساسية. أثناء هذا التسلسل، يتم نقل دور المرحلة الأساسية إلى نسخة متماثلة أخرى (أو يعود) دون إيقاف عملية تشغيل الخدمة. أخيرا، يجب أن نفكر في حالات الخطأ أو الفشل.
بدء عملية تشغيل الخدمة عديمة الحالة.
دورة حياة الخاص بالخدمة عديمة الحالة واضح. ما يلي هو ترتيب الأحداث:
- تم إنشاء الخدمة.
- بعد ذلك، بالتوازي، يحدث شيئان:
StatelessService.CreateServiceInstanceListeners()يتم استدعاؤه ويتم فتح أي وحدات استماع تم إرجاعها.ICommunicationListener.OpenAsync()يتم استدعاؤه على كل وحدة استماع.- يتم استدعاء أسلوب الخدمة
StatelessService.RunAsync().
- إذا كانت موجودة، يتم استدعاء أسلوب الخدمة
StatelessService.OnOpenAsync(). تُعد هذه المكالمة تجاوز غير شائع، ولكنها متوفرة. يمكن بدء مهام تهيئة الخدمة القابلة للتوسيع في الوقت الحالي.
يُرجى الوضع في الاعتبار أنه لا يوجد ترتيب بين المكالمات لإنشاء وحدات الاستماع وفتحهم و RunAsync. يمكن إجراء عملية فتح لوحدات الاستماع قبل بدء تشغيل RunAsync . وبالمثل، يمكنك استدعاء RunAsync قبل أن تكون وحدات استماع الاتصال مفتوحين أو حتى مبنيين. إذا كانت يوجد حاجة إلى أي مزامنة، يجب تركها كتمرين للمنفذ. أدناه بعض الحلول الشائعة:
- في بعض الأحيان لا يمكن لوحدات الاستماع بدء العمل حتى يتم إنشاء بعض المعلومات الأخرى أو الانتهاء من العمل. بالنسبة للخدمات عديمة الحالة، يمكن عادة القيام بهذا العمل في مواقع أخرى، مثل ما يلي:
- في الدالة الإنشائية للخدمة.
- أثناء بدء المكالمة
CreateServiceInstanceListeners(). - كجزء من بناء وحدة الاستماع نفسها.
- في بعض الأحيان لا يبدأ تشغيل التعليمة البرمجية في RunAsync حتى يتم فتح وحدات الاستماع. في هذه الحالة ، التنسيق الإضافي أمر ضروري. أحد الحلول الشائعة هو أن هناك علامة داخل وحدات الاستماع تشير إلى وقت انتهائهم. ثم يتم التحقق من هذه العلامة في RunAsync قبل متابعة العمل الفعلي.
إيقاف تشغيل الخدمة عديمة الحالة.
لإيقاف تشغيل خدمة عديمة الحالة، يجب اتباع نفس النمط، في الاتجاه المعاكس تماما:
- بصورة متوازية:
- يتم إغلاق أي وحدات استماع مفتوحين.
ICommunicationListener.CloseAsync()يتم استدعاؤه على كل وحدة استماع. - يتم إلغاء رمز الإلغاء المميز الذي تم تمريره
RunAsync()إليه. يؤدي التحقق من خاصية رمز الإلغاء المميزIsCancellationRequestedإلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميزThrowIfCancellationRequestedيتم التخلص منهOperationCanceledException.
- يتم إغلاق أي وحدات استماع مفتوحين.
- بعد
CloseAsync()الانتهاء من كل وحدة استماع والإنهاءRunAsync()أيضا، يتم استدعاء أسلوب الخدمة، إذا كانStatelessService.OnCloseAsync()موجودة. يتم استدعاء OnCloseAsync عند إيقاف تشغيل مثيل الخدمة عديم الحالة بأمان. يمكن أن يحدث هذا عند ترقية التعليمات البرمجية للخدمة أو نقل مثيل الخدمة بسبب موازنة التحميل أو اكتشاف خطأ انتقالي. من غير الشائع التجاوزStatelessService.OnCloseAsync()، ولكن يمكن استخدامه من أجل إغلاق الموارد بأمان أو إيقاف عملية معالجة الخلفية أو إنهاء حفظ الحالة الخارجية أو إغلاق الاتصالات الموجودة. - بعد انتهاء
StatelessService.OnCloseAsync()، يجب تدمير عنصر الخدمة.
بدء تشغيل الخدمة ذات الحالة
الخدمات ذات الحالة لها نمط مماثل للخدمات عديمة الخالة، مع وجود بعض التغييرات. لبدء تشغيل الخدمة ذات الحالة، يكون ترتيب الأحداث كما يلي:
- تم إنشاء الخدمة.
StatefulServiceBase.OnOpenAsync()التسمية. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.- تقع الأشياء التالية بالتوازي:
StatefulServiceBase.CreateServiceReplicaListeners()يتم الاستناد إليها.- إذا كانت الخدمة خدمة أساسية، يجب فتح كافة وحدات الاستماع الذين تم إرجاعهم.
ICommunicationListener.OpenAsync()يتم استدعاؤه على كل وحدة استماع. - إذا كانت الخدمة خدمة ثانوية، فلن يتم فتح سوى وحدات الاستماع الذين تم وضع علامة
ListenOnSecondary = trueعليهم. وجود وحدات استماع مفتوحة على المرتبات الثانوية أقل شيوعا.
- إذا كانت الخدمة خدمة أساسية، يجب فتح كافة وحدات الاستماع الذين تم إرجاعهم.
- إذا كانت الخدمة الحالية أساسية، يجب استدعاء أسلوب الخدمة
StatefulServiceBase.RunAsync().
- بعد انتهاء كافة مكالمات
OpenAsync()وحدة الاستماع المتماثلة وRunAsync()استدعاؤها،StatefulServiceBase.OnChangeRoleAsync()تتم عملية الاستدعاء. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.
على غرار الخدمات عديمة الحالة، لا يوجد تنسيق بين الأمر الذي يتم به إنشاء وحدات الاستماع وفتحهم وعندما يتم استدعاء RunAsync . إذا كنت بحاجة إلى التنسيق، فإن الحلول متشابهة إلى حد كبير. هناك حالة إضافية واحدة للخدمة ذات الحالة. لنفترض أن المكالمات التي تصل إلى وحدات استماع الاتصالات تتطلب معلومات محفوظة داخل بعض المجموعات الموثوقة.
ملاحظة
نظرا لأن وحدات استماع الاتصال يمكنهم الفتح قبل أن تكون المجموعات الموثوقة قابلة للقراءة أو الكتابة ، وقبل أن يبدأ RunAsync، فمن الضروري إجراء بعض التنسيق الإضافي. الحل الأبسط والأكثر شيوعا هو أن تقوم وحدات استماع الاتصال بإرجاع التعليمة البرمجية للخطأ اليت يستخدمها كمبيوتر العميل لمعرفته لإعادة محاولة الطلب.
إيقاف تشغيل الخدمة ذات الحالة.
مثل الخدمات عديمة الحالة، تكون أحداث دورة الحياة أثناء إيقاف التشغيل هي نفسها أثناء بدء التشغيل ، ولكن يتم عكسها. عند إيقاف تشغيل خدمة حالة، تحدث الأحداث التالية:
بصورة متوازية:
- يتم إغلاق أي وحدات استماع مفتوحين.
ICommunicationListener.CloseAsync()يتم استدعاؤه على كل وحدة استماع. - يتم إلغاء رمز الإلغاء المميز الذي تم تمريره
RunAsync()إليه. يؤدي التحقق من خاصية رمز الإلغاء المميزIsCancellationRequestedإلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميزThrowIfCancellationRequestedيتم التخلص منهOperationCanceledException.
- يتم إغلاق أي وحدات استماع مفتوحين.
بعد
CloseAsync()الانتهاء من كل مستمع والانتهاءRunAsync()أيضا، يتم استدعاء الخدمةStatefulServiceBase.OnChangeRoleAsync(). عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.ملاحظة
تُعتبر الحاجة إلى الانتظار حتى ينتهي RunAsync أمر ضروري فقط إذا كانت هذه النسخة المتماثلة نسخة متماثلة أساسية.
بعد انتهاء أسلوب
StatefulServiceBase.OnChangeRoleAsync()، يتم استدعاء أسلوبStatefulServiceBase.OnCloseAsync(). تُعد هذه المكالمة تجاوز غير شائع، ولكنها متوفرة.بعد انتهاء
StatefulServiceBase.OnCloseAsync()، يجب تدمير عنصر الخدمة.
المبادلات الأساسية للخدمات ذات الحالة
أثناء تشغيل خدمة الحالة، يتم فتح وحدات استناع الاتصال فقط واستدعاء أسلوب RunAsync الخاصة بهم فقط. يتم بناء نسخ ثانوية متماثلة، ولكن لا ترى أي مكالمات أخرى. أثناء تشغيل خدمة ذات حالة، يمكن أن تتغير النسخة المتماثلة الموجودة حاليا "الأساسية" نتيجة لتحسين موازنة الخطأ أو نظام المجموعة. ماذا معنى هذا من حيث أحداث دورة الحياة التي يمكن أن تراها النسخة المتماثلة؟ يعتمد السلوك الذي تراه النسخة المتماثلة ذات الحالة على ما إذا كانت النسخة المتماثلة التي يتم تخفيضها أو الترويج لها أثناء المبادلة.
بالنسبة للمرحلة الأساسية التي تم تخفيض رتبتها
بالنسبة للنسخة المتماثلة الأساسية التي تم تخفيض رتبتها، يحتاج تصميم الخدمة إلى هذه النسخة المتماثلة لإيقاف معالجة الرسائل وإنهاء أي عمل في الخلفية يقوم به. ونتيجة لذلك، تبدو هذه الخطوة متشابهة عند إيقاف تشغيل الخدمة. أحد أوجه الاختلاف هو أن الخدمة لا يتم تدميرها أو إغلاقها لأنها تظل ثانوية. تُدعى واجهات برمجة التطبيقات التالية:
- بصورة متوازية:
- يتم إغلاق أي وحدات استماع مفتوحين.
ICommunicationListener.CloseAsync()يتم استدعاؤه على كل وحدة استماع. - يتم إلغاء رمز الإلغاء المميز الذي تم تمريره
RunAsync()إليه. يؤدي التحقق من خاصية رمز الإلغاء المميزIsCancellationRequestedإلى إرجاع true، وإذا تم استدعاؤها، فإن أسلوب الرمز المميزThrowIfCancellationRequestedيتم التخلص منهOperationCanceledException.
- يتم إغلاق أي وحدات استماع مفتوحين.
- بعد
CloseAsync()الانتهاء من كل مستمع والانتهاءRunAsync()أيضا، يتم استدعاء الخدمةStatefulServiceBase.OnChangeRoleAsync(). عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.
بالنسبة بالمرحلة الثانوية التي تمت ترقيتها
وبالمثل، تحتاج تصميم الخدمة إلى النسخة المتماثلة الثانوية التي تمت ترقيتها لبدء تشغيل وحدة الاستماع فيما يتعلق بالرسائل الموجودة على السلك وبدء أي مهام في الخلفية تحتاج إلى إكمالها. ونتيجة لذلك، تبدو هذه العملية متشابهة عند إنشاء الخدمة، باستثناء أن النسخة المتماثلة نفسها موجودة بالفعل. تُدعى واجهات برمجة التطبيقات التالية:
- بصورة متوازية:
StatefulServiceBase.CreateServiceReplicaListeners()يتم استدعاؤه ويتم فتح أي وحدات استماع تم إرجاعها.ICommunicationListener.OpenAsync()يتم استدعاؤه على كل وحدة استماع.- يتم استدعاء طريقة الخدمة
StatefulServiceBase.RunAsync().
- بعد انتهاء كافة مكالمات
OpenAsync()وحدة الاستماع المتماثلة وRunAsync()استدعاؤها،StatefulServiceBase.OnChangeRoleAsync()تتم عملية الاستدعاء. عدم تجاوز هذه المكالمة بشكل شائع في الخدمة.
المشكلات الشائعة أثناء إيقاف تشغيل الخدمة وخفض الرتبة الأساسي
يغير تصميم الخدمة الأساسي للخدمة ذات الحالة لمجموعة متنوعة من الأسباب. الأكثر شيوعا هي إعادة توازن نظام المجموعةوترقية التطبيق. أثناء إجراء هذه العمليات (وكذلك أثناء إيقاف تشغيل الخدمة العادي، كما لو كنت ترى ما إذا تم حذف الخدمة)، من المهم أن تحترم CancellationTokenالخدمة .
يمكن أن تواجه الخدمات التي لا تعالج عملية الإلغاء بشكل نظيف العديد من المشكلات. هذه العمليات بطيئة لأن تصميم الخدمة ينتظر توقف الخدمات بأمان. هذا يمكن أن يؤدي في نهاية المطاف إلى حدوث ترقيات فاشلة في ذلك الوقت وتتراجع. يمكن أن يؤدي الفشل في احترام رمز الإلغاء المميز أيضا إلى نظام مجموعات غير متوازنة. سبب عدم توازن نظام المجموعات هو أن العقد تصبح ساخنة، ولكن لا يمكن إعادة توازن الخدمات لأن نقلها إلى مكان آخر يستغرق وقتا طويلا.
نظرا لأن الخدمات ذات حالة جيدة، فمن المحتمل أيضا أنها تستخدم مجموعات موثوقة. في تصميم الحدمة، عندما يتم تخفيض رتبة المرحلة الأساسية، فإن أحد الأشياء الأولى التي تحدث هو إبطال وصول الكتابة إلى الحالة الأساسية. هذا من شأنه أن يؤدي إلى مجموعة ثانية من المشكلات التي يمكن أن تؤثر على دورة حياة الخدمة. تعمل المجموعات على إرجاع الاستثناءات استنادا إلى التوقيت وما إذا كان يتم نقل النسخة المتماثلة أو إيقاف تشغيلها. يتطلب التعامل مع هذه الاستثناءات بشكل صحيح. تقع الاستثناءات التي تم طرحها بواسطة Service Fabric ضمن الفئات الدائمة (FabricException) وعابرة (FabricTransientException) . يجب تسجيل الاستثناءات الدائمة والتخلص منها بينما يمكن إعادة محاولة الاستثناءات المؤقتة بناء على بعض منطق إعادة المحاولة.
يُعتبر التعامل مع الاستثناءات الناتجة عن استخدام الخدمة بالتزامن مع أحداث دورة حياة الخدمة جزءا مهما من اختبار الخدمة ReliableCollections الموثوقة والتحقق من صحتها. نوصي دائما بتشغيل الخدمة الخاصة بك تحت الحمل أثناء إجراء الترقيات واختبار الفوضى قبل النشر المتعلق بعملية الإنتاج. تساعد هذه الخطوات الأساسية على ضمان تنفيذ الخدمة بشكل صحيح ومعالجة أحداث المتعلقة بدورة الحياة بشكل صحيح.
ملاحظات بشأن دورة حياة الخدمة
- كل من
RunAsync()الأسلوب والمكالماتCreateServiceReplicaListeners/CreateServiceInstanceListenersاختيارية. يمكن أن تشمل الخدمة على واحدة منهم، كلاهما ، أو لا. على سبيل المثال، إذا كانت الخدمة تقوم بكل مهامها استجابة لمكالمات المستخدم، فليست هناك حاجة لإجراء عملية تنفيذهاRunAsync(). فقط وحدات استماع الاتصالات والتعليمات البرمجية المرتبطة بهم ضرورية. وبالمثل، فإن إنشاء وحدات استماع الاتصال وإعادتهم أمر اختياري، حيث يمكن أن يكون للخدمة عمل أساسي فقط للقيام به، وبالتالي تحتاج فقط إلى التنفيذRunAsync(). - حيث أنها صالحة لإكمال الخدمة
RunAsync()بنجاح والاسترجاع. لا يُعد الإكمال شرطا للفشل. يشير الإكمالRunAsync()إلى انتهاء العمل الأساسي الخاص بالخدمة. بالنسبة للخدمات الموثوقة ذات الحالة،RunAsync()يتم استدعاؤها مرة أخرى إذا تم تخفيض رتبة النسخة المتماثلة من الأساسية إلى الثانوية ثم ترقيتها مرة أخرى إلى أساسية. - إذا خرجت خدمة من
RunAsync()عن طريق التخلص من بعض الاستثناءات غير المتوقعة، فهذا يشكل فشلا. يتم إيقاف تشغيل عنصر الخدمة ويتم الإبلاغ عن خطأ صحي. - على الرغم من عدم وجود حد زمني لاسترجاع هذه الأساليب، إلا أنك تفقد على الفور القدرة على الكتابة المتعلقة بمجموعات موثوقة، وبالتالي لا يمكنك إكمال أي عمل حقيقي. نوصي بالمواصلة في أسرع وقت ممكن عند استلام طلب الإلغاء. إذا لم تستجب خدمتك لمكالمات واجهة برمجة التطبيقات هذه في فترة زمنية معقولة، فيمكن لتصميم الخدمة إنهاء خدمتك قسراً. عادة ما يحدث هذا فقط أثناء ترقيات التطبيق أو عند القيام بحذف خدمة. مدة المهلة هي 15 دقيقة بشكل افتراضي.
- تؤدي حالات الإخفاق في المسار
OnCloseAsync()إلى استدعاءOnAbort()، وهي فرصة أخيرة لفرصة بذل أفضل مجهود للخدمة للتنظيف والإفراج عن أي موارد طالبوا بملكيتها. يتم استدعاء هذا بشكل عام عند اكتشاف خطأ دائم في العقدة، أو عندما يتعذر على تصميم الخدمة إدارة دورة حياة مثيل الخدمة بشكل موثوق بسبب الأعطال الداخلية. OnChangeRoleAsync()يتم استدعاؤه عندما تقوم النسخة المتماثلة الخاصة بالخدمة ذات الحالة بتغيير الدور، على سبيل المثال إلى أساسي أو ثانوي. يتم إعطاء النسخ المتماثلة الأساسية ميزة حالة الكتابة (يسمح لها بإنشاء وكتابة مجموعات موثوقة). يتم منح النسخ المتماثلة الثانوية ميزة حالة قراءة (يمكن قراءتها فقط من المجموعات الموثوقة الموجودة). يتم تنفيذ معظم العمل في خدمة الحالة بأسلوب النسخة المتماثلة الأساسية. يمكن للنسخ المتماثلة الثانوية إجراء التحقق من صحة القراءة فقط أو إنشاء التقارير أو استخراج البيانات أو مهام أخرى للقراءة فقط.