نمط قائمة انتظار الأولوية

Azure Service Bus

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

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

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

حل

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

رسم تخطيطي يوضح آلية قائمة الانتظار التي تدعم ترتيب أولويات الرسائل.

إشعار

تدعم معظم تطبيقات قائمة انتظار الرسائل العديد من المستهلكين. (راجع نمط المستهلكين المتنافسين.) يمكن توسيع نطاق عدد عمليات المستهلكين صعودا وهبوطا بناء على الطلب.

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

رسم تخطيطي يوضح استخدام قوائم انتظار رسائل منفصلة لكل أولوية.

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

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

يمكن أن يوفر استخدام آلية ترتيب الأولويات المزايا التالية:

  • يسمح للتطبيقات بتلبية متطلبات العمل التي تتطلب تحديد أولويات التوفر أو الأداء، مثل تقديم مستويات مختلفة من الخدمة لمجموعات مختلفة من العملاء.

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

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

الاعتبارات

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

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

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

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

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

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

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

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

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

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

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

هذا النمط مفيد في السيناريوهات حيث:

  • يجب أن يتعامل النظام مع مهام متعددة لها أولويات مختلفة.

  • يجب تقديم أولويات مختلفة للمستخدمين أو المستأجرين المختلفين.

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

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

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

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

- PE:09 التدفقات الحرجة

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

مثال

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

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

رسم تخطيطي يوضح كيفية تنفيذ قائمة انتظار ذات أولوية باستخدام مواضيع واشتراكات ناقل خدمة Microsoft Azure.

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

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

يستند حل PriorityQueue على GitHub إلى هذا النهج. يحتوي هذا الحل على مشاريع Azure Function المسماة PriorityQueueConsumerHigh وPriorityQueueConsumerLow. تتكامل مشاريع Azure Function هذه مع ناقل خدمة Microsoft Azure عبر المشغلات والروابط. وهي تتصل باشتراكات مختلفة يتم تعريفها في ServiceBusTrigger الرسائل الواردة وتتفاعل معها.

public static class PriorityQueueConsumerHighFn
{
    [FunctionName("HighPriorityQueueConsumerFunction")]
    public static void Run(
      [ServiceBusTrigger("messages", "highPriority", Connection = "ServiceBusConnection")]string highPriorityMessage,
      ILogger log)
    {
        log.LogInformation($"C# ServiceBus topic trigger function processed message: {highPriorityMessage}");
    }
}

بصفتك مسؤولا، يمكنك تكوين عدد المثيلات التي يمكن للوظائف في Azure App Service توسيع نطاقها إليها. يمكنك القيام بذلك عن طريق تكوين الخيار Enforce Scale Out Limit من مدخل Microsoft Azure، وتعيين حد أقصى للتوسيع لكل وظيفة. تحتاج عادة إلى مثيلات الدالة PriorityQueueConsumerHigh أكثر من الدالة PriorityQueueConsumerLow . يضمن هذا التكوين قراءة الرسائل ذات الأولوية العالية من قائمة الانتظار بسرعة أكبر من الرسائل ذات الأولوية المنخفضة.

يحتوي مشروع آخر، PriorityQueueSender، على دالة Azure مشغلة زمنيا يتم تكوينها للتشغيل كل 30 ثانية. تتكامل هذه الدالة مع ناقل خدمة Microsoft Azure عبر ربط إخراج وترسل دفعات من الرسائل ذات الأولوية المنخفضة والعالية إلى كائن IAsyncCollector . عندما تنشر الدالة رسائل إلى الموضوع المرتبط بالاشتراكات المستخدمة من قبل PriorityQueueConsumerHigh الدالتين و PriorityQueueConsumerLow ، فإنها تحدد الأولوية باستخدام الخاصية Priority المخصصة، كما هو موضح هنا:

public static class PriorityQueueSenderFn
{
    [FunctionName("PriorityQueueSenderFunction")]
    public static async Task Run(
        [TimerTrigger("0,30 * * * * *")] TimerInfo myTimer,
        [ServiceBus("messages", Connection = "ServiceBusConnection")] IAsyncCollector<ServiceBusMessage> collector)
    {
        for (int i = 0; i < 10; i++)
        {
            var messageId = Guid.NewGuid().ToString();
            var lpMessage = new ServiceBusMessage() { MessageId = messageId };
            lpMessage.ApplicationProperties["Priority"] = Priority.Low;
            lpMessage.Body = BinaryData.FromString($"Low priority message with Id: {messageId}");
            await collector.AddAsync(lpMessage);

            messageId = Guid.NewGuid().ToString();
            var hpMessage = new ServiceBusMessage() { MessageId = messageId };
            hpMessage.ApplicationProperties["Priority"] = Priority.High;
            hpMessage.Body = BinaryData.FromString($"High priority message with Id: {messageId}");
            await collector.AddAsync(hpMessage);
        }
    }
}

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

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

  • عينة توضح هذا النمط، على GitHub.

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

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

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

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

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