نمط المستهلكين المنافسين

Azure Functions
Azure Service Bus

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

السياق والمشكلة

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

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

حل

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

استخدام قائمة انتظار الرسائل لتوزيع العمل على مثيلات الخدمة

إشعار

على الرغم من وجود العديد من المستهلكين لهذه الرسائل، إلا أن هذا ليس هو نفس نمط نشر الاشتراك (pub/sub). باستخدام نهج المستهلكين المتنافسين، يتم تمرير كل رسالة إلى مستهلك واحد للمعالجة، بينما مع نهج Pub/Sub، يتم تمرير جميع المستهلكين كل رسالة.

يكون لهذا الحل المزايا التالية:

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

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

  • لا يتطلب تنسيقا معقدا بين المستهلكين أو بين مثيلات المنتِج والمستهلك. تضمن قائمة انتظار الرسائل تسليم كل رسالة مرة واحدة على الأقل.

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

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

المسائل والاعتبارات

راع النقاط التالية عند تحديد كيفية تنفيذ هذا النمط:

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

    يمكن لMicrosoft Azure Service Bus Queues تنفيذ ترتيب مضمون للرسائل ما يرد أولا يصدر أولا باستخدام جلسات عمل الرسائل. لمزيد من المعلومات، راجع «أنماط المراسلة باستخدام جلسات العمل».

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

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

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

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

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

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

موعد استخدام النمط

استخدم هذا النمط عندما:

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

قد لا يكون هذا النمط مفيدًا في الحالات الآتية:

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

تدعم بعض أنظمة المراسلة جلسات العمل التي تمكن المنتِج من تجميع الرسائل معا والتأكد من معالجتها جميعا بواسطة نفس المستهلك. يمكن استخدام هذه الآلية مع الرسائل ذات الأولوية (إذا كانت مدعومة) لتنفيذ شكل من أشكال ترتيب الرسائل الذي يسلم الرسائل بالتسلسل من منتِج إلى مستهلك واحد.

تصميم حمل العمل

يجب على المهندس المعماري تقييم كيفية استخدام نمط المستهلكين المتنافسين في تصميم حمل العمل الخاص بهم لمعالجة الأهداف والمبادئ التي تغطيها ركائز Azure Well-Architected Framework. على سبيل المثال:

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

- RE:05 التكرار
- وظائف الخلفية RE:07
يركز تحسين التكلفة على الحفاظ على عائد حمل العمل على الاستثمار وتحسينه. يمكن أن يساعدك هذا النمط على تحسين التكاليف عن طريق تمكين التحجيم استنادا إلى عمق قائمة الانتظار، وصولا إلى الصفر عندما تكون قائمة الانتظار فارغة. كما يمكنه تحسين التكاليف من خلال تمكينك من الحد الأقصى لعدد مثيلات المستهلك المتزامنة.

- تحسين معدل CO:05
- تكاليف مكون CO:07
تساعد كفاءة الأداء حمل العمل الخاص بك على تلبية الطلبات بكفاءة من خلال التحسينات في التحجيم والبيانات والرمز. يؤدي توزيع الحمل عبر جميع عقد المستهلك إلى زيادة الاستخدام والتحجيم الديناميكي استنادا إلى عمق قائمة الانتظار وتقليل الإفراط في التوفير.

- PE:05 التحجيم والتقسيم
- PE:07 Code والبنية الأساسية

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

مثال

يقدم Azure Service Bus Queues ومشغلات قائمة انتظار Azure Function التي هي تنفيذ مباشر لنمط تصميم السحابة هذا عند دمجها. يتكامل Azure Functions مع Azure Service Bus عبر المشغلات والروابط. يسمح لك التكامل مع Service Bus بإنشاء دوال تستهلك رسائل قائمة الانتظار المرسلة من الناشرين. سينشر تطبيق (تطبيقات) النشر الرسائل إلى قائمة انتظار ويمكن للمستهلكين، الذين تم تنفيذهم ك Azure Functions، استرداد الرسائل من قائمة الانتظار هذه والتعامل معها.

للمرونة، تمكن قائمة انتظار Service Bus المستهلك من استخدام الوضع PeekLock عندما يسترد رسالة من قائمة الانتظار، لا يزيل هذا الوضع الرسالة فعليا، ولكنه يخفيها ببساطة عن المستهلكين الآخرين. يتلقى وقت تشغيل Azure Functions رسالة في وضع PeekLock، إذا انتهت الدالة بنجاح فتستدعي Complete على الرسالة أو قد تستدعي Abandon إذا فشلت الدالة، وستصبح الرسالة مرئية مرة أخرى، مما يسمح لمستهلك آخر باستردادها. في حالة تشغيل الدالة لفترة أطول من مهلة PeekLock، يتم تجديد القفل تلقائيًا طالما كانت الدالة قيد التشغيل.

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

للحصول على معلومات مفصلة حول استخدام قوائم انتظار Azure Service Bus راجع قوائم انتظار Service Bus والموضوعات والاشتراكات.

للحصول على معلومات حول Azure Functions قد التشغيل في قائمة الانتظار، راجع مشغل Azure Service Bus ل Azure Functions.

توضح التعليمات البرمجية التالية كيفية إنشاء رسالة جديدة وإرسالها إلى قائمة انتظار Service Bus باستخدام مثيل ServiceBusClient.

private string serviceBusConnectionString = ...;
...

  public async Task SendMessagesAsync(CancellationToken  ct)
  {
   try
   {
    var msgNumber = 0;

    var serviceBusClient = new ServiceBusClient(serviceBusConnectionString);

    // create the sender
    ServiceBusSender sender = serviceBusClient.CreateSender("myqueue");

    while (!ct.IsCancellationRequested)
    {
     // Create a new message to send to the queue
     string messageBody = $"Message {msgNumber}";
     var message = new ServiceBusMessage(messageBody);

     // Write the body of the message to the console
     this._logger.LogInformation($"Sending message: {messageBody}");

     // Send the message to the queue
     await sender.SendMessageAsync(message);

     this._logger.LogInformation("Message successfully sent.");
     msgNumber++;
    }
   }
   catch (Exception exception)
   {
    this._logger.LogException(exception.Message);
   }
  }

يظهر مثال التعليمات البرمجية التالي مستهلكا مكتوبا كC# Azure Function يقرأ بيانات تعريف الرسالة ويسجل رسالة Service Bus Queue. لاحظ كيفية استخدام السمة ServiceBusTrigger لربطها ب Service Bus Queue.

[FunctionName("ProcessQueueMessage")]
public static void Run(
    [ServiceBusTrigger("myqueue", Connection = "ServiceBusConnectionString")]
    string myQueueItem,
    Int32 deliveryCount,
    DateTime enqueuedTimeUtc,
    string messageId,
    ILogger log)
{
    log.LogInformation($"C# ServiceBus queue trigger function consumed message: {myQueueItem}");
    log.LogInformation($"EnqueuedTimeUtc={enqueuedTimeUtc}");
    log.LogInformation($"DeliveryCount={deliveryCount}");
    log.LogInformation($"MessageId={messageId}");
}

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

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

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

قد تكون الأنماط والإرشادات التالية ذات صلة أيضًا عند تنفيذ هذا النمط:

  • نمط حساب دمج الموارد. قد يكون من الممكن دمج مثيلات متعددة لخدمة المستهلك في معالجة واحدة لتقليل التكاليف والمصاريف الإضافية للإدارة. يوضح نمط «حساب دمج الموارد» مزايا ومفاضلات اتباع هذا النهج.

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