موفر Azure Storage (Azure Functions)

يصف هذا المستند خصائص موفر Azure Storage لـ Durable Functions، مع التركيز على جوانب الأداء وقابلية التوسع. موفر Azure Storage هو الموفر الافتراضي. يخزن حالات المثيل وقوائم الانتظار في حساب Azure Storage (كلاسيكي).

إشعار

لمزيد من المعلومات حول موفرو التخزين المختلفين لـ Durable Functions وكيفية مقارنتهم، راجع وثائق موفرو تخزين Durable Functions.

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

تمثيل التخزين

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

يشكل موفر Azure Storage مركز المهام في التخزين باستخدام المكونات التالية:

  • بين جدولين وثلاثة جداول Azure. يتم استخدام جدولين لتمثيل المخازن وحالات المثيل. إذا تم تمكين Table Partition Manager، فسيتم تقديم جدول ثالث لتخزين معلومات القسم.
  • تخزن Azure Queue واحدة رسائل النشاط.
  • تقوم قائمة أو أكثر من Azure Queues بتخزين رسائل المثيل. تمثل كل من قوائم انتظار التحكم هذه قسمًا تم تعيينه لمجموعة فرعية من جميع رسائل المثيل، بناءً على تجزئة معرف المثيل.
  • عدد قليل من حاويات الكائنات الثنائية كبيرة الحجم المستخدمة لتأجير الكائنات الثنائية كبيرة الحجم و/أو الرسائل الكبيرة.

على سبيل المثال، يحتوي مركز المهام المسمى xyz بـ PartitionCount = 4 على قوائم الانتظار والجداول التالية:

Diagram showing Azure Storage provider storage storage organization for 4 control queues.

وبعد ذلك، نصف هذه المكونات والدور الذي تلعبه بمزيد من التفصيل.

جدول المحفوظات

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

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

تلميح

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

جدول المثيلات

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

يستخدم هذا الجدول لتلبية طلبات استعلام المثيل من التعليمات البرمجية وكذلك استدعاءات HTTP API لاستعلام الحالة. وفي النهاية يتم الاحتفاظ به متسقًا مع محتويات جدول المحفوظات المذكور سابقًا. إن استخدام جدول Azure Storage منفصل لتلبية عمليات استعلام المثيل بكفاءة بهذه الطريقة يتأثر بنمط الفصل بين مسؤولية الأوامر والاستعلام (CQRS).

تلميح

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

جدول الأقسام

إشعار

يظهر هذا الجدول في مركز المهام فقط عند Table Partition Manager تمكينه. لتطبيقه، قم بتكوين useTablePartitionManagement الإعداد في host.json الخاص بتطبيقك.

يخزن جدول الأقسام حالة الأقسام لتطبيق Durable Functions ويستخدم لتوزيع الأقسام عبر العاملين في التطبيق. يوجد صف واحد لكل قسم.

الصفوف

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

قائمة انتظار عنصر العمل.

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

قائمة (قوائم) انتظار التحكم

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

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

يتم استطلاع رسائل قائمة انتظار التحكم باستمرار باستخدام مؤشر ترابط الخلفية. يتم التحكم في حجم الدفعة لكل استطلاع قائمة انتظار بواسطة إعداد controlQueueBatchSize في host.json ويحتوي على 32 بشكل افتراضي (القيمة القصوى المدعومة من قبل Azure Queues). يتم التحكم في الحد الأقصى لعدد رسائل قائمة انتظار التحكم التي تم تخزينها مؤقتًا في الذاكرة بواسطة إعداد controlQueueBufferThreshold في host.json. تختلف القيمة الافتراضية لـ controlQueueBufferThreshold بناءً على مجموعة متنوعة من العوامل، بما في ذلك نوع خطة الاستضافة. لمزيد من المعلومات حول هذه الإعدادات، راجع وثائق مخطط host.json.

تلميح

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

استطلاع قائمة الانتظار

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

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

إشعار

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

تأخيرات بدء التنسيق

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

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

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

الكائنات الثنائية كبيرة الحجم

في معظم الحالات، لا يستخدم Durable Functions الكائنات الثنائية كبيرة الحجم في Azure Storage للاحتفاظ بالبيانات. ومع ذلك، فإن قوائم الانتظار والجداول لها حدود حجم يمكن أن تمنع Durable Functions من الاحتفاظ بجميع البيانات المطلوبة في صف تخزين أو رسالة قائمة انتظار. على سبيل المثال، عندما يكون جزء من البيانات المطلوب الاحتفاظ بها في قائمة انتظار أكبر من 45 كيلو بايت عند تسلسله، فإن Durable Functions سيقوم بضغط البيانات وتخزينها في كائن ثنائي كبير الحجم بدلاً من ذلك. عند الاحتفاظ بالبيانات في مخزن الكائنات الثنائية كبيرة الحجم بهذه الطريقة، يقوم Durable Functions بتخزين مرجع إلى ذلك الكائن الثنائي كبير الحجم في صف الجدول أو رسالة قائمة الانتظار. عندما يحتاج Durable Functions إلى استرداد البيانات، فسيقوم تلقائيًا بإحضارها من الكائن الثنائي كبير الحجم. يتم تخزين هذه الكائنات الثنائية كبيرة الحجم في حاوية الكائنات الثنائية كبيرة الحجم <taskhub>-largemessages.

الاعتبارات الخاصة بالأداء

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

تحديد حساب التخزين

يتم إنشاء قوائم الانتظار والجداول والكائنات الثنائية كبيرة الحجم المستخدمة بواسطة Durable Functions في حساب Azure Storage مُكوّن. يمكن تحديد الحساب المراد استخدامه باستخدام إعداد durableTask/storageProvider/connectionStringName (أو إعداد durableTask/azureStorageConnectionStringName في Durable Functions 1.x) في ملف host.json.

الدوال الدائمة 2.x

{
  "extensions": {
    "durableTask": {
      "storageProvider": {
        "connectionStringName": "MyStorageAccountAppSetting"
      }
    }
  }
}

Durable Functions 1.x

{
  "extensions": {
    "durableTask": {
      "azureStorageConnectionStringName": "MyStorageAccountAppSetting"
    }
  }
}

إذا لم يتم تحديده، يتم استخدام حساب تخزين AzureWebJobsStorage الافتراضي. ومع ذلك، بالنسبة لأحمال العمل الحساسة للأداء، يوصى بتكوين حساب تخزين غير افتراضي. تستخدم Durable Functions خدمة Azure Storage بكثرة، ويؤدي استخدام حساب تخزين مخصص إلى عزل استخدام تخزين Durable Functions عن الاستخدام الداخلي من قبل مضيف Azure Functions.

إشعار

يلزم توفر حسابات Azure Storage للأغراض العامة القياسية عند استخدام موفر Azure Storage. جميع أنواع حسابات التخزين الأخرى غير مدعومة. نوصي بشدة باستخدام حسابات تخزين الأغراض العامة القديمة v1 لـ Durable Functions. يمكن أن تكون حسابات تخزين v2 الأحدث أكثر تكلفة بكثير لأحمال عمل Durable Functions. لمزيد من المعلومات حول أنواع حسابات التخزين في Azure، راجع وثائق نظرة عامة على حساب التخزين.

توسيع نطاق المنسق

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

إشعار

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

يتم تحديد عدد قوائم انتظار التحكم في ملف host.json. المثال التالي لقصاصات host.json البرمجية يعيّن خاصية durableTask/storageProvider/partitionCount (أو durableTask/partitionCount في Durable Functions 1.x) على 3. لاحظ أن هناك العديد من قوائم انتظار التحكم بعدد الأقسام الموجودة.

الدوال الدائمة 2.x

{
  "extensions": {
    "durableTask": {
      "storageProvider": {
        "partitionCount": 3
      }
    }
  }
}

Durable Functions 1.x

{
  "extensions": {
    "durableTask": {
      "partitionCount": 3
    }
  }
}

يمكن تكوين مركز مهام باستخدام 1 إلى 16 قسمًا. إذا لم يتم تحديده، يبلغ عدد الأقسام الافتراضي 4.

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

Scale-in orchestrations diagram

في الرسم التخطيطي السابق، نرى أن التنسيقات من 1 إلى 6 متوازنة التحميل عبر الأقسام. وبالمثل، فإن الأقسام، مثل الأنشطة، متوازنة التحميل عبر العاملين. الأقسام متوازنة التحميل عبر العاملين بغض النظر عن عدد التنسيقات التي بدأت.

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

First scaled-out orchestrations diagram

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

إشعار

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

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

Second scaled-out orchestrations diagram

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

يوضح الرسم التخطيطي التالي كيفية تفاعل مضيف Azure Functions مع كيانات التخزين في بيئة موسعة.

Scale diagram

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

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

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

جلسات العمل الموسعة

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

يمكنك تمكين جلسات العمل الموسعة عن طريق تعيين durableTask/extendedSessionsEnabled على true في ملف host.json. يمكن استخدام إعداد durableTask/extendedSessionIdleTimeoutInSeconds للتحكم في المدة التي سيتم فيها الاحتفاظ بجلسة عمل خاملة في الذاكرة:

الدوال 2.0

{
  "extensions": {
    "durableTask": {
      "extendedSessionsEnabled": true,
      "extendedSessionIdleTimeoutInSeconds": 30
    }
  }
}

الدوال 1.0

{
  "durableTask": {
    "extendedSessionsEnabled": true,
    "extendedSessionIdleTimeoutInSeconds": 30
  }
}

هناك جانبان سلبيان محتملان لهذا الإعداد يجب إدراكهما:

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

على سبيل المثال، إذا تم تعيين durableTask/extendedSessionIdleTimeoutInSeconds على 30 ثانية، فإن حلقة دالة منسق أو كيان قصيرة الأجل يتم تنفيذها في أقل من 1 ثانية ستظل تشغل الذاكرة لمدة 30 ثانية. كما أنها تُحسب مقابل حصة durableTask/maxConcurrentOrchestratorFunctions النسبية المذكورة سابقًا، مما قد يمنع تشغيل دوال المنسق أو الكيان الأخرى.

يتم توضيح التأثيرات المحددة لجلسات العمل الموسعة على دوال المنسق والكيان في الأقسام التالية.

إشعار

لا يتم دعم جلسات العمل الموسعة حاليًا إلا بلغات .NET، مثل C# أو F#. يمكن أن يؤدي تعيين extendedSessionsEnabled على true للأنظمة الأساسية الأخرى إلى مشكلات في وقت التشغيل، مثل الفشل بصمت في تنفيذ الدوال المشغلة بواسطة النشاط والتنسيق.

إعادة تشغيل دوال المنسق

كما ذُكر سابقًا، يتم إعادة تشغيل دوال المنسق باستخدام محتويات جدول المحفوظات. بشكل افتراضي، يتم إعادة تشغيل التعليمات البرمجية لدالة المنسق في كل مرة يتم فيها حذف دفعة رسائل من قائمة انتظار التحكم. حتى إذا كنت تستخدم نمط توزيع المهام إلى عدة وجهات، توزيع المهام إلى نفس الوجهة وكنت في انتظار اكتمال جميع المهام (على سبيل المثال، استخدام Task.WhenAll() في .NET أو context.df.Task.all() في JavaScript أو context.task_all() في Python)، ستحدث عمليات إعادة تشغيل عندما يتم معالجة دفعات من استجابات المهام بمرور الوقت. عند تمكين جلسات العمل الموسعة، يتم الاحتفاظ بمثيلات دالة المنسق في الذاكرة لفترة أطول ويمكن معالجة الرسائل الجديدة دون إعادة تشغيل محفوظات كاملة.

غالبًا ما يتم ملاحظة تحسين أداء جلسات العمل الموسعة في الحالات التالية:

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

في كافة المواقف الأخرى، لا يوجد عادة أي تحسن ملحوظ في الأداء لدوال المنسق.

إشعار

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

أهداف الأداء

يعرض الجدول التالي الحد الأقصى المتوقع لأرقام معدل النقل للسيناريوهات الموضحة في قسم أهداف الأداء في مقالة الأداء والمقياس.

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

السيناريو الحد الأقصى لمعدل النقل
تنفيذ النشاط التسلسلي 5 أنشطة في الثانية، لكل مثيل
تنفيذ النشاط المتوازي (توزيع المهام إلى عدة وجهات) 100 نشاط في الثانية، لكل مثيل
معالجة الاستجابة المتوازية (توزيع المهام إلى نفس الوجهة) 150 استجابة في الثانية، لكل مثيل
معالجة الأحداث الخارجية 50 حدث في الثانية، لكل مثيل
معالجة عملية الكيان 64 عملية في الثانية

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

تلميح

في بعض الحالات، يمكنك زيادة معدل نقل الأحداث الخارجية، وتوزيع مهام النشاط إلى نفس الوجهة، وعمليات الكيان بشكل ملحوظ عن طريق زيادة قيمة إعداد controlQueueBufferThreshold في host.json. يؤدي زيادة هذه القيمة بما يتجاوز قيمتها الافتراضية في أن يستخدم موفر تخزين Durable Task Framework ذاكرة أكثر لجلب هذه الأحداث مسبقًا بقوة أكبر، مما يقلل من التأخيرات المقترنة بحذف الرسائل من قوائم انتظار التحكم في Azure Storage. لمزيدٍ من المعلومات، يُرجى مراجعة الوثائق المرجعية لـ host.json.

معالجة ذات معدل نقل مرتفع

إن تصميم خلفية Azure Storage يضع بعض القيود على الحد الأقصى للأداء النظري وقابلية توسع Durable Functions. إذا أظهر اختبارك أن Durable Functions على Azure Storage لن تفي بمتطلبات معدل النقل لديك، فيجب عليك بدلاً من ذلك استخدام موفر تخزين Netherite لـ Durable Functions.

لمقارنة معدل النقل القابل للتحقيق لمختلف السيناريوهات الأساسية، راجع القسم السيناريوهات الأساسية لوثائق موفر تخزين Netherite.

تم تصميم خلفية تخزين Netherite وتطويرها من قبل Microsoft Research. حيث تستخدم Azure Event Hubs وتكنولوجيا قاعدة بيانات FASTER على رأس Azure Page Blobs. يتيح تصميم Netherite معالجة ذات معدل نقل أعلى بكثير لعمليات التنسيق والكيانات مقارنة بالموفرين الآخرين. في بعض السيناريوهات القياسية، شهد معدل النقل زيادة كبيرة من حيث ترتيب الحجم عند مقارنته بموفر Azure Storage الافتراضي.

لمزيد من المعلومات حول موفرو التخزين المختلفين لـ Durable Functions وكيفية مقارنتهم، راجع وثائق موفرو تخزين Durable Functions.

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