تحسين أداء ووثوقية Azure Functions

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

فيما يلي أفضل الممارسات لكيفية إنشاء وتصميم الحلول بلا خادم باستخدام Azure Functions.

تجنب الوظائف طويلة الأمد

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

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

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

تأكد من اكتمال مهام الخلفية

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

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

اتصال عبر الوظائف

صُمم كل من Durable Functions وAzure Logic Apps لإدارة المراحل الانتقالية للحالة والاتصال بين الوظائف المتعددة.

إذا كنت لا تستخدم Durable Functions أو Logic Apps للتكامل مع وظائف متعددة، فمن الأفضل استخدام قوائم انتظار التخزين للاتصال عبر الوظائف. السبب الرئيسي وراء هذا هو أن قوائم انتظار التخزين أقل تكلفة وأسهل بكثير في توفيرها مقارنة بخيارات التخزين الأخرى.

يقتصر حجم الرسائل الفردية في قائمة انتظار التخزين على 64 كيلو بايت. إذا كنت بحاجة إلى تمرير رسائل أكبر بين الوظائف، يمكن استخدام قائمة انتظار ناقل خدمة Microsoft Azure لدعم أحجام الرسائل التي تصل إلى 256 كيلوبايت في المستوى Standard، وما يصل إلى 100 ميغابايت في المستوى Premium.

يمكنك الاستفادة من مواضيع ناقل الخدمة إذا كنت تحتاج إلى تصفية الرسائل قبل المعالجة.

يمكن الاستفادة من مراكز الأحداث لدعم الاتصالات ذات الحجم الكبير.

كتابة وظائف عديمة الحالة

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

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

كتابة وظائف دفاعية

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

  1. الاستعلام عن 10000 صف في قاعدة بيانات.
  2. أنشئ رسالة قائمة انتظار لكل من هذه الصفوف لمعالجة سطر آخر لأسفل.

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

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

إذا كان أحد عناصر قائمة الانتظار قد تمت معالجته بالفعل، فاسمح للوظيفة أن تكون بدون تشغيل.

استفد من التدابير الدفاعية المقدمة مسبقاً للمكونات التي تستخدمها في النظام الأساسي لـ Azure Functions. على سبيل المثال، راجع معالجة قوائم انتظار الرسائل الضارة في الوثائق الخاصة بـ بالمشغّلات وروابط البيانات لـ Azure Storage Queue.

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

أفضل ممارسات تنظيم الوظائف

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

تنظيم وظائف الأداء وتغيير السعة

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

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

ملاحظة

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

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

تنظيم وظائف للتكوين والتوزيع

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

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

تنظيم الوظائف حسب الامتياز

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

أفضل الممارسات لقابلية التوسع

يوجد عدد من العوامل التي تؤثر على كيفية تغيير سعة مثيلات تطبيق الوظائف. التفاصيل المتوفرة في وثائق تغيير سعة الوظيفة. فيما يلي بعض من أفضل الممارسات لضمان قابلية التوسع لتطبيق الوظائف.

مشاركة الاتصالات وإدارتها

أعد استخدام الاتصالات على الموارد الخارجية كلما أمكن ذلك. راجع كيفية إدارة الاتصالات في Azure Functions.

تجنب مشاركة حسابات التخزين

عند إنشاء تطبيق وظائف، يجب إقرانه بحساب تخزين. يتم الاحتفاظ باتصال حساب التخزين في إعداد تطبيق AzureWebJobsStorage.

لتحقيق أقصى قدر من الأداء، استخدم حساب تخزين منفصل لكل تطبيق وظائف. هذا مهم بشكل خاص عندما يكون لديك وظائف دائمة أو وظائف مشغلة لمركز الأحداث، وكلاهما يولد حجماً كبيراً من عمليات التخزين. عندما يتفاعل منطق التطبيق الخاص بك مع Azure Storage، إما مباشرةً (باستخدام SDK للتخزين) أو من خلال أحد روابط التخزين، يجب عليك استخدام حساب تخزين مخصص. على سبيل المثال، إذا كانت لديك وظيفة مشغّل Event Hub تكتب بعض البيانات إلى تخزين الكائن الثنائي كبير الحجم، فاستخدم حسابي تخزين - أحدهما لتطبيق الدالة والآخر للكائنات الثنائية كبيرة الحجم التي تُخزنها الدالة.

لا تخلط بين التعليمة البرمجية للإنتاج والاختبار في تطبيق الوظائف نفسه

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

توخى الحذر عند التحميل في تطبيقات وظائف الإنتاج. عبر كل وظيفة في التطبيق يكون حجم الذاكرة متوسطاً.

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

لا تستخدم تسجيل verbose في التعليمة البرمجية للإنتاج، والذي له تأثير سلبي على الأداء.

استخدام التعليمات البرمجية غير المتزامنة مع تجنب حظر الاتصالات

البرمجة غير المتزامنة هي إحدى أفضل الممارسات الموصى بها، خاصة عند حظر عمليات الإدخال/الإخراج.

في C#، تجنب الرجوع إلى خاصية Result أو أسلوب الاستدعاء Waitفي مثيل Task. يمكن أن يؤدي هذا النهج إلى استنفاد مؤشر الترابط.

تلميح

إذا كنت تخطط لاستخدام روابط HTTP أو WebHook، فخطط لتجنب استنفاد المنفذ الذي يمكن أن يحدث بسبب إنشاء مثيل غير صحيح لـ HttpClient. لمزيد من المعلومات، راجع كيفية إدارة الاتصالات في وظائف Azure.

استخدام عمليات العامل المتعددة

بشكل افتراضي، يستخدم أي مثيل مضيف لـ Functions عملية واحدة للعامل. لتحسين الأداء، خاصة مع أوقات التشغيل أحادية مؤشر الترابط مثل Python، استخدم FUNCTIONS_WORKER_PROCESS_COUNT لزيادة عدد عمليات معالجة العامل لكل مضيف (حتى 10). يحاول Azure Functions بعد ذلك توزيع استدعاءات الوظيفة المتزامنة عبر هذه العوامل بالتساوي.

ينطبق FUNCTIONS_WORKER_PROCESS_COUNT على كل مضيف تنشئه الوظائف عند تغيير سعة تطبيقك لتلبية الطلب.

تلقي الرسائل على دفعات كلما أمكن

تتيح بعض المشغّلات مثل Event Hub إمكانية تلقي دفعة من الرسائل في استدعاء واحد. إرسال الرسائل في دفعات له أداء أفضل بكثير. يمكنك تكوين الحد الأقصى لحجم الدُفعة في ملف host.json كما هو مفصل في الوثائق المرجعية host.json

بالنسبة إلى وظائف C#، يمكنك تغيير النوع إلى صفيف قوي. على سبيل المثال بدلاً من EventData sensorEvent، يمكن أن يكون توقيع الأسلوب EventData[] sensorEvent. بالنسبة إلى اللغات الأخرى، ستحتاج إلى تعيين خاصية علاقة أساسية في function.json على many من أجل إرسال في دفعات كما هو موضح هنا.

تكوين سلوكيات المضيف للتعامل مع التزامن بشكل أفضل

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

تنطبق الإعدادات في ملف host.json على جميع الوظائف داخل التطبيق، ضمن مثيل واحد في الوظيفة. على سبيل المثال، إذا كان لديك تطبيق وظائف بوظيفتي HTTP وطلبات maxConcurrentRequests معينة على 25، فسيُحسب الطلب إلى أي مشغّل HTTP مع الطلبات المتزامنة المشتركة الـ 25. عندما يتم تغيير سعة تطبيق الوظائف هذا ليسع ما يصل إلى 10 مثيلات، فستسمح الوظائف العشرة فعلياً بـ 250 طلبًا متزامناً (10 مثيلات * 25 طلباً متزامناً لكل مثيل).

تم العثور على خيارات تكوين المضيف الأخرى في مقالة تكوين host.json.

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

لمزيد من المعلومات، راجع الموارد التالية: