فهم وسطاء الرسائل. تعلم آليات المراسلة من خلال ActiveMQ و Kafka. الفصل 2. ActiveMQ

استمرار ترجمة كتاب صغير:
"فهم وسطاء الرسائل" ،
المؤلف: Jakub Korab ، الناشر: O'Reilly Media، Inc. ، تاريخ النشر: يونيو 2017 ، ISBN: 9781492049296.

اكتملت الترجمة

الجزء السابق: فهم وسطاء الرسائل. تعلم آليات المراسلة من خلال ActiveMQ و Kafka. الفصل 1. مقدمة

الفصل 2


ActiveMQ


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

تم تطوير ActiveMQ كتطبيق لمواصفات خدمة رسائل Java (JMS). تم اتخاذ هذا القرار للوفاء بمتطلبات تنفيذ المراسلة المتوافقة مع JMS في مشروع Apache Geronimo ، وهو خادم تطبيق J2EE مفتوح المصدر.
يتكون نظام المراسلة (أو الوسيطة الموجهة للرسائل ، كما يطلق عليه في بعض الأحيان) التي تنفذ مواصفات JMS من المكونات التالية:

وسيط

قطعة مركزية من الوسيطة التي توزع الرسائل.

زبون

جزء البرنامج الذي يرسل الرسائل من خلال وسيط. يتكون ، بدوره ، من القطع الأثرية التالية:

  • رمز باستخدام واجهة برمجة تطبيقات JMS.
  • واجهة برمجة تطبيقات JMS هي مجموعة من واجهات التفاعل مع وسيط وفقًا للضمانات المنصوص عليها في مواصفات JMS.
  • مكتبة العميل الخاصة بالنظام الذي يوفر تطبيق API ويتفاعل مع الوسيط.

يتواصل العميل والوسيط مع بعضهما البعض من خلال بروتوكول طبقة التطبيق ، المعروف أيضًا باسم بروتوكول التفاعل (الشكل 2-1) . ترك مواصفات JMS تفاصيل هذا البروتوكول إلى تطبيقات محددة.


الشكل 2-1. مراجعة JMS

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

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

كان لهذه المنطقة ، كما سنرى لاحقًا ، تأثير كبير على أداء ActiveMQ. بالإضافة إلى تعقيدات الوسيط ، فإن حزمة التوافق للمواصفات التي توفرها Sun Microsystems لها العديد من الفروق الدقيقة ، مع تأثيرها الخاص على الأداء. يجب أن تؤخذ جميع هذه الفروق الدقيقة في الاعتبار من أجل اعتبار ActiveMQ متوافقًا مع JMS.

صلة


على الرغم من أن API والسلوك المتوقع تم تحديدهما جيدًا في مواصفات JMS ، إلا أنه تم استبعاد بروتوكول الاتصال الفعلي للعميل من المواصفات عملاً حتى يمكن جعل الوسطاء الحاليين متوافقين مع JMS. وبالتالي ، كان ActiveMQ حرًا في تعريف بروتوكول التفاعل الخاص به ، OpenWire. يتم استخدام OpenWire من خلال تطبيق مكتبة عملاء ActiveMQ JMS ، وكذلك نظرائه في .Net و C ++: NMS و CMS ، وهما مشروعان فرعيان لـ ActiveMQ تستضيفهما مؤسسة Apache Software Foundation.

بمرور الوقت ، تمت إضافة دعم بروتوكولات التفاعل الأخرى إلى ActiveMQ ، مما زاد من القدرة على التفاعل مع اللغات والبيئات الأخرى:

AMQP 1.0

لا ينبغي الخلط بين بروتوكول انتظار الرسائل المتقدم (ISO / IEC 19464: 2014) مع سابقه 0.X ، والذي يتم تنفيذه في أنظمة المراسلة الأخرى ، ولا سيما RabbitMQ ، باستخدام 0.9.1. 1.0 AMQP هو بروتوكول ثنائي للأغراض العامة لتبادل الرسائل بين العقدتين. لا يوجد لديه مفهوم للعملاء أو الوسطاء ويتضمن وظائف مثل التحكم في التدفق والمعاملات وجودة الخدمة المختلفة (ليس أكثر من مرة ، مرة واحدة على الأقل ، ومرة ​​واحدة بالضبط).

ستومب

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

XMPP

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

MQTT

بروتوكول اشتراك النشر الخفيف (ISO / IEC 20922: 2016) المستخدم لتطبيقات من آلة إلى آلة (M2M) وتطبيقات إنترنت الأشياء (IoT).

يدعم ActiveMQ أيضًا فرض البروتوكولات أعلاه على WebSockets ، والذي يوفر تبادل بيانات مزدوج الاتجاه بين التطبيقات في مستعرض ويب والوجهات في الوسيط.

نظرًا لهذا ، الآن عندما نتحدث عن ActiveMQ ، لم نعد نشير حصريًا إلى رصة التفاعل استنادًا إلى مكتبات JMS / NMS / CMS وبروتوكول OpenWire. أصبح الجمع بين اللغات والأنظمة الأساسية والمكتبات الخارجية التي تناسب هذا التطبيق واختياره أكثر شيوعًا. على سبيل المثال ، يمكن تشغيل تطبيق JavaScript في مستعرض باستخدام مكتبة Eclipse Paho MQTT لإرسال رسائل إلى ActiveMQ عبر مآخذ الويب ، وتتم قراءة هذه الرسائل بواسطة عملية خادم C ++ تستخدم AMQP من خلال مكتبة Apache Qpid Proton . من هذا المنظور ، أصبح مشهد المراسلة أكثر تنوعًا.

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

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

المفاضلة بين الأداء والموثوقية


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

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

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

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

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

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

حفظ الرسائل


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

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

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

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

عوامل أداء القرص


هناك عدد من العوامل التي تحدد السرعة التي يمكن أن يعمل بها القرص. لفهم ذلك ، فكر في طريقة الكتابة إلى القرص من خلال نموذج عقلي مبسط للأنبوب ( الشكل 2-2 ).


الشكل 2-2. نموذج أنبوب أداء القرص

الأنبوب له ثلاثة أبعاد:

طول

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

عرض

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

عرض النطاق الترددي مع مرور الوقت

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

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

JMS API


قبل الدخول في تفاصيل كيفية اتصال ActiveMQ مع العملاء ، نحتاج أولاً إلى معرفة واجهة برمجة تطبيقات JMS. يعرّف API مجموعة من واجهات البرمجة المستخدمة بواسطة رمز العميل:

ConnectionFactory

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

صلة

هذا كائن طويل العمر يشبه اتصال TCP تقريبًا - بعد الإنشاء ، عادة ما يكون موجودًا طوال دورة حياة التطبيق بالكامل حتى يتم إغلاقه. الاتصال آمن للخيط ويمكنه العمل مع عدة خيوط في وقت واحد. تسمح لك كائنات الاتصال بإنشاء كائنات الجلسة.

جلسة

هذا مؤشر دفق عند التفاعل مع وسيط. كائنات جلسة العمل غير آمنة لمؤشر الترابط ، مما يعني أنه لا يمكن الوصول إليها بواسطة مؤشرات ترابط متعددة في نفس الوقت. الجلسة هي واصف المعاملات الرئيسي الذي يمكن للمبرمج أن يرسل ويعيد رسائل التراجع إذا كان في وضع المعاملات. باستخدام هذا الكائن ، يمكنك إنشاء كائنات MessageConsumer و MessageProducer ، وكذلك الحصول على مؤشرات (واصفات) إلى كائنات Topic و Queue.

MessageProducer

تتيح لك هذه الواجهة إرسال رسالة إلى المستلم.

MessageConsumer

تسمح هذه الواجهة للمطور باستلام الرسائل. هناك آليتان لاستعادة الرسائل:

  • تسجيل MessageListener. هذه هي واجهة معالج الرسائل التي قمت بتطبيقها ، والتي ستقوم بمعالجة أي رسائل صادرة عن الوسيط باستخدام تيار واحد.
  • استقصاء الرسائل باستخدام طريقة التلقي ().

رسالة

ربما هذا هو الهيكل الأكثر أهمية لأنه ينقل بياناتك. تتكون الرسائل في JMS من جانبين:

  • بيانات التعريف للرسالة. تحتوي الرسالة على رؤوس وخصائص. كل ذلك ، وهذا يمكن اعتباره عناصر من الخريطة. الرؤوس عبارة عن عناصر معروفة معروفة بواسطة مواصفات JMS ومتاحة مباشرة من خلال واجهة برمجة التطبيقات ، مثل JMSDestination و JMSTimestamp. الخصائص هي أجزاء عشوائية من معلومات الرسائل التي تم تعيينها لتبسيط معالجة الرسائل أو توجيهها دون الحاجة إلى قراءة حمولة الرسالة نفسها. يمكنك ، على سبيل المثال ، تعيين الرأس إلى AccountID أو OrderType.
  • نص الرسالة. يمكن إنشاء عدة أنواع مختلفة من الرسائل من الجلسة بناءً على نوع المحتوى الذي سيتم إرساله في النص ، وأكثرها شيوعًا هي TextMessage للسلاسل و BytesMessage للبيانات الثنائية.

كيف تعمل قوائم الانتظار: قصة ثنائية المخ


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

إرسال الرسائل إلى قائمة الانتظار


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


الشكل 2-3. إرسال الرسائل إلى JMS

في تطبيق العميل ، يتلقى مؤشر الترابط مؤشرًا إلى MessageProducer. يقوم بإنشاء رسالة ذات حمولة رسالة تقديرية ويستدعي MessageProducer.send ("الطلبات" ، الرسالة) ، مع قائمة الانتظار كوجهة أخيرة للرسالة. نظرًا لعدم رغبة المبرمج في فقد الرسالة في حالة تعطل الوسيط ، تم تعيين رأس الرسالة JMSDeliveryMode على PERSISTENT (السلوك الافتراضي).

في هذه المرحلة (1) ، يستدعي الدفق المرسل مكتبة العميل ويقوم بتنظيم الرسالة بتنسيق OpenWire. ثم يتم إرسال الرسالة إلى الوسيط.

في الوسيط ، يقوم الدفق المتلقي بإزالة الرسالة من الخط وإلغاء تنظيمها على الكائن الداخلي. بعد ذلك ، يتم إرسال كائن الرسالة إلى مهايئ الثبات ، الذي ينظم الرسالة باستخدام تنسيق Google Protocol Buffers ويكتبها إلى وحدة التخزين (2).
بعد تسجيل الرسالة في وحدة التخزين ، يجب أن يتلقى مهايئ الثبات تأكيدًا على تسجيل الرسالة فعليًا (3). هذا هو عادةً أبطأ جزء من التفاعل بالكامل ؛ المزيد عن هذا في وقت لاحق.

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

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

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

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

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

مخابئ ، مخابئ في كل مكان


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

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

الكتابة

إلى القرص فور استلامها.

Writeback (كتابة خلفية)

يتم إجراء التسجيل على الأقراص فقط عندما يصل المخزن المؤقت إلى قيمة عتبة معينة.

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

عند العودة إلى وسيط الرسائل ، يلزمك إكمال خطوة التأكيد للتأكد من أن البيانات قد وصلت بالفعل إلى القرص. لسوء الحظ ، فإن التفاعل مع هذه المخازن المؤقتة للأجهزة يعتمد على نظام الملفات ، لذلك كل ما يمكن أن تفعله عملية مثل ActiveMQ هو إرسال إشارة إلى نظام الملفات بأنها تريد مزامنة جميع المخازن المؤقتة للنظام مع الجهاز قيد الاستخدام. للقيام بذلك ، يقوم الوسيط باستدعاء طريقة java.io.FileDescriptor.sync () ، والتي بدورها تبدأ عملية POSIX fsync ().

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

الصراعات الداخلية


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

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

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

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

المعاملات


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

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

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


الشكل 2-4. إرسال الرسائل في المعاملات

في هذا النوع من العمليات ، يستخدم ActiveMQ تحسينين لزيادة السرعة:

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

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

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


تبدأ عملية قراءة الرسائل عندما يعرب المستهلك عن استعداده لقبولها إما عن طريق إعداد MessageListener لمعالجة الرسائل فور وصولها ، أو عن طريق استدعاء الأسلوب MessageConsumer.receive () ( الشكل 2-5 ).


الشكل 2-5. قراءة الرسائل من خلال JMS

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

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

في مرحلة ما بعد الدخول في مخزن الجلب المسبق ، تتم قراءة الرسائل بواسطة منطق التطبيق (X) ويتم إرسال تأكيد التدقيق إلى الوسيط (3). تم تكوين توقيت الوقت بين معالجة الرسائل والتأكيد باستخدام معلمة جلسة JMS تسمى وضع الإقرار ، والتي سنناقشها لاحقًا.
بمجرد أن يقبل الوسيط تأكيد تسليم الرسالة ، يتم حذفه من الذاكرة ومن مخزن الرسائل (4). مصطلح "الحذف" مضلل إلى حد ما ، لأنه في الواقع يتم كتابة سجل تأكيد للمجلة ويزيد المؤشر في الفهرس. سيتم تنفيذ الحذف الفعلي لملف السجل الذي يحتوي على الرسالة بواسطة أداة تجميع مجمعي البيانات المهملة في مؤشر ترابط الخلفية استنادًا إلى هذه المعلومات.

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

وسائط التأكيد والمعاملة


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

AUTO_ACKNOWLEDGE

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

CLIENT_ACKNOWLEDGE

سيتم إرسال تأكيد فقط عندما يقوم رمز العميل باستدعاء أسلوب Message.acknowledge () بشكل صريح.

DUPS_OK_ACKNOWLEDGE

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

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

إيفاد والعديد من المستهلكين


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

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

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

يثير هذا سؤالًا مهمًا: حتى في حالة استخدام معاملات المستهلكين ، لا يوجد ضمان بعدم معالجة الرسالة عدة مرات.

النظر في منطق المعالجة التالية داخل المستهلك:

  1. يتم طرح الرسالة من قائمة الانتظار. تبدأ المعاملة.
  2. يتم استدعاء خدمة الويب مع محتويات الرسالة.
  3. المعاملة ملتزمة. يتم إرسال تأكيد إلى الوسيط.

إذا اكتمل العميل بين الخطوتين 2 و 3 ، فقد أثر التدقيق اللغوي للرسالة بالفعل على نظام آخر عن طريق الاتصال بخدمة الويب. مكالمات خدمة الويب هي طلبات HTTP ، وبالتالي فهي ليست معاملات.

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

لا يوجد شيء مثل تسليم الرسائل مرة واحدة فقط .

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

ترتيب الرسائل


بالنسبة لمجموعة من الرسائل التي تصل بترتيب [A ، B ، C ، D] ، وبالنسبة للمستهلكين C1 و C2 ، سيكون التوزيع الطبيعي للرسائل على النحو التالي:

C1: [A, C]
C2: [B, D]

نظرًا لأن الوسيط لا يتحكم في تشغيل عمليات القراءة وأن ترتيب المعالجة متوازي ، فهو غير حاسم. إذا كانت C1 أبطأ من C2 ، فيمكن معالجة المجموعة الأولى من الرسائل كـ [B ، D ، A ، C].

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

خذ حالة الاستخدام التالية المأخوذة من المراهنة عبر الإنترنت كمثال:

  1. تم تكوين حساب المستخدم.
  2. يتم إضافة الأموال إلى الحساب.
  3. يتم المراهنة على سحب الأموال من الحساب.

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

يتضمن نموذج العميل الحصري إرسال جميع الرسائل من قائمة الانتظار إلى عميل واحد. باستخدام هذا النهج ، عند توصيل مثيلات متعددة للتطبيقات أو my.queue?consumer.exclusive=true الانتظار ، يتم توقيعها باستخدام معلمة مستلم خاص: my.queue?consumer.exclusive=true . عند توصيل مستهلك احتكار ، يتلقى جميع الرسائل. عندما يكون المستهلك الثاني متصلاً ، لن يتلقى أي رسائل حتى يتم قطع اتصال العميل الأول. هذا المستهلك الثاني هو في الواقع احتياطي ساخن ، في حين سيتلقى المستهلك الأول الآن رسائل بالضبط بالترتيب الذي تم تسجيله به في المجلة - بترتيب سببي.
أما عيب هذا الأسلوب فهو أنه على الرغم من أن معالجة الرسائل متسقة ، إلا أنها تمثل اختناقًا في الأداء نظرًا لأن جميع الرسائل يجب معالجتها بواسطة جهاز compurator واحد.

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

مجموعات الرسائل هي نوع من آليات التقسيم التي تسمح للمنتجين بتوزيع الرسائل في مجموعات ستتم معالجتها بالتسلسل وفقًا لمفتاح العمل. يتم تعيين مفتاح العمل هذا في خاصية رسالة تسمى JMSXGroupID .

سيكون المفتاح الطبيعي في حالة معالجة العطاءات هو معرف الحساب.
لتوضيح كيفية عمل الإرسال ، ضع في اعتبارك مجموعة من الرسائل التي تصل بالترتيب التالي:

 [(A, Group1), (B, Group1), (C, Group2), (D, Group3), (E, Group2)] 

عندما تتم معالجة رسالة بواسطة آلية الإرسال في ActiveMQ JMSXGroupID لم تكن موجودة من قبل ، يتم تعيين هذا المفتاح للمستهلك على أساس دوري. من الآن فصاعدًا ، سيتم إرسال جميع الرسائل بهذا المفتاح إلى هذا المحاسب.

سيتم تعيين المجموعات هنا بين مستهلكين: C1 و C2 ، على النحو التالي:

 C1: [Group1, Group3] C2: [Group2] 

سيتم إعادة توجيه الرسائل ومعالجتها على النحو التالي:

 C2: [B, D] C2: [(C, Group2), (E, Group2)] 

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

عالية التوفر


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


الشكل 2-6. الوسيط A هو الرائد ؛ الوسيط B في وضع الاستعداد كعبد

للاتصال بالمستودع ، يتولى الوسيط الأول (الوسيط A) دور القائد ويفتح منافذه لحركة مرور الرسائل. عندما يتصل الوسيط الثاني (Broker B) بالمستودع ، يحاول الحصول على قفل ، ولأنه لم ينجح ، يتوقف لفترة قصيرة قبل محاولة الحصول على القفل مرة أخرى. وهذا ما يسمى الاحتواء مدفوعة.

في الوقت نفسه ، يقوم العميل بالتبديل بين عناوين الوسيطين في محاولة للاتصال بالمنفذ الوارد ، المعروف باسم موصل النقل. بمجرد توفر الوسيط الرئيسي ، يتصل العميل بمنفذه ويمكنه إرسال الرسائل وقراءتها.
عندما يفشل الوسيط A ، الذي يتصرف كقائد ، بسبب فشل العملية ( الشكل 2-7 ) ، تحدث الأحداث التالية:

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


الشكل 2-7. ينتهي الوسيط A بفقد الاتصال بالمستودع. وسيط B يأخذ زمام المبادرة
لا يتم ضمان منطق التناوب بين عدة عناوين وسيط في مكتبة العميل ، كما هو الحال في تطبيقات JMS / NMS / CMS. إذا كانت المكتبة توفر فقط إعادة الاتصال بعنوان واحد ، فقد تحتاج إلى وضع اثنين من الوسطاء وراء موازن التحميل ، والذي يجب أن يكون متاحًا أيضًا بدرجة كبيرة.
العيب الرئيسي لهذا النهج هو أنه لتبسيط عمل وسيط منطقي واحد ، هناك حاجة إلى عدة خوادم فعلية. في هذه الحالة ، يكون أحد خادمي الوسيط خاملاً ، في انتظار انقطاع شريكه قبل أن يبدأ العمل.

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

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

لضمان التشغيل المستقر للوسيط ، يلزم تخزين مخصص وحصري.

التحجيم الرأسي والأفقي


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

هناك عدة طرق للحصول على أداء أكثر من البنية التحتية للوسيط:

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

  1. عدة أقراص داخل وسيط واحد ، على سبيل المثال ، باستخدام محول الثبات mKahaDB للعديد من الدلائل ، كل منها مثبت على قرص منفصل.
  2. يتم تنفيذ العديد من الوسطاء وتقسيم حركة المرور يدويًا بواسطة تطبيق العميل. لا يوفر ActiveMQ أي وظائف أصلية لهذا الغرض.

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

تنشأ المشكلة غالبًا أثناء مرحلة تصميم النظام ، عندما يستطيع مهندس النظام اقتراح مثل هذا المخطط كما في الشكل 2-8 .


الشكل 2-8. عرض مفاهيمي للبنية التحتية للرسائل

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

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


الشكل 2-9. تدفقات رسالة الرسم بين الأنظمة

بعد موافقتها ، يمكنك الذهاب إلى التفاصيل للإجابة على الأسئلة التالية:

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

تتمثل الفكرة في تحديد سيناريوهات منفصلة للمراسلة يمكن دمجها أو تقسيمها بواسطة وسطاء فرديين ( الشكل 2-10 ).
بعد هذا الانهيار ، يمكن محاكاة سيناريوهات الاستخدام من خلال الجمع مع بعضها البعض باستخدام وحدة الأداء ActiveMQ لتحديد أي مشاكل.


الشكل 2-10. تحديد الوسطاء الفرديين

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

النتائج


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

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

الجزء التالي: فهم وسطاء الرسائل. تعلم آليات المراسلة من خلال ActiveMQ و Kafka. الفصل 3. كافكا

اكتملت الترجمة: tele.gg/middle_java

Source: https://habr.com/ru/post/ar471268/


All Articles