فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا

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

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

الفصل 3

كافكا

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

بالنظر إلى هذا الهدف النهائي ، نشأت متطلبات أخرى بشكل طبيعي. يجب على كافكا:

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

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

نموذج الوجهة الموحدة

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

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

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

المصطلحان "log" و "pointer" لا يظهران في وثائق كافكا. تستخدم هذه المصطلحات المعروفة هنا للمساعدة في الفهم.

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

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-1. أقسام كافكا

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

قراءة الرسائل

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

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

يمكن تمثيل مشكلة القراءة على النحو التالي:

  • الموضوع له أقسام متعددة
  • يمكن لمجموعات متعددة من المستهلكين استخدام موضوع في نفس الوقت
  • يمكن أن يكون لمجموعة من المستهلكين عدة حالات منفصلة

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

المستهلكون ومجموعات المستهلكين

لنأخذ كنقطة بداية موضوعًا ذا قسم واحد (الرقم 3-2).

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-2. يقرأ المستهلك من القسم

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

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

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-3. يقوم مستهلكان في مجموعات مستهلكين مختلفة بالقراءة من نفس القسم

المستهلكون في مجموعة المستهلكين

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

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-4. يقرأ مستهلكان في نفس مجموعة المستهلكين من نفس القسم

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

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

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

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

الطريقة المتعارف عليها لحل هذه المشكلة في كافكا هي استخدام بОالمزيد من الأقسام.

التقسيم

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

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-5. مستهلك واحد يقرأ من أقسام متعددة

في هذا السيناريو ، يُمنح المستهلك التحكم في المؤشرات المقابلة لمعرّف المجموعة الخاص به في كلا القسمين ويبدأ في قراءة الرسائل من كلا القسمين.
عند إضافة مستهلك إضافي لنفس group_id إلى هذا الموضوع ، يعيد كافكا تخصيص أحد الأقسام من المستهلك الأول إلى المستهلك الثاني. بعد ذلك ، سيقرأ كل مثيل للمستهلك من قسم واحد للموضوع (الرقم 3-6).

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

فهم وسطاء الرسائل. تعلم آليات المراسلة باستخدام ActiveMQ و كافكا. الفصل 3. كافكا
الشكل 3-6. اثنان من المستهلكين في نفس مجموعة المستهلكين يقرؤون من أقسام مختلفة

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

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

كل ما على وسيط كافكا فعله هو تمرير الرسائل بشكل متسلسل إلى المستهلك عندما يطلبها الأخير.

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

إرسال الرسائل

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

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

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

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

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

تبدو هذه الواجهة كما يلي:

interface Partitioner {
    int partition(String topic,
        Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster);
}

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

كتابة استراتيجية التقسيم الخاصة بك

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

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

{
  "signature": "541661622185851c248b41bf0cea7ad0",
  "accountId": "10007865234"
}

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

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

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

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

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

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

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

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

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

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

اتفاقيات المنتجين

التقسيم ليس الشيء الوحيد الذي يجب مراعاته عند إرسال الرسائل. دعنا نلقي نظرة على طرق الإرسال () لفئة المنتج في Java API:

Future < RecordMetadata > send(ProducerRecord < K, V > record);
Future < RecordMetadata > send(ProducerRecord < K, V > record, Callback callback);

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

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

RecordMetadata metadata = producer.send(record).get();

المزيد عن قراءة الرسائل

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

ConsumerRecords < K, V > poll(long timeout);

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

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

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

بالعودة إلى نموذج القراءة الذي تمت مناقشته سابقًا ، تتكون معالجة الرسائل من ثلاث مراحل:

  1. استرجع رسالة لقراءتها.
  2. قم بمعالجة الرسالة.
  3. تأكيد الرسالة.

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

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

في كافكا 0.10 ، تم تغيير رمز العميل بحيث يتم تشغيل الالتزام بشكل دوري بواسطة مكتبة العميل ، كما تم تكوينه auto.commit.interval.ms. يقع هذا السلوك في مكان ما بين وضعي JMS AUTO_ACKNOWLEDGE و DUPS_OK_ACKNOWLEDGE. عند استخدام الالتزام التلقائي ، يمكن الالتزام بالرسائل بغض النظر عما إذا كانت قد تمت معالجتها بالفعل - يمكن أن يحدث هذا في حالة المستهلك البطيء. إذا تم إحباط المستهلك ، فسيتم جلب الرسائل من قبل المستهلك التالي ، بدءًا من موضع الالتزام ، مما قد يؤدي إلى فقدان رسالة. في هذه الحالة ، لم يفقد كافكا الرسائل ، ولم يقم رمز القراءة بمعالجتها.

هذا الوضع له نفس الوعد كما في الإصدار 0.9: يمكن معالجة الرسائل ، ولكن إذا فشلت ، فقد لا يتم الالتزام بالإزاحة ، مما قد يتسبب في مضاعفة التسليم. كلما زاد عدد الرسائل التي تجلبها عند التنفيذ تصويت()، كلما زادت هذه المشكلة.

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

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

يمكنك التحكم في عملية الالتزام اليدوي في واجهة برمجة تطبيقات مستهلك كافكا من خلال تعيين المعلمة تمكين.auto.commit إلى false واستدعاء إحدى الطرق التالية صراحة:

void commitSync();
void commitAsync();

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

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

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

إذا لم نتمكن من الاعتماد على المعاملات ، فكيف يمكننا توفير دلالات أقرب إلى تلك التي توفرها أنظمة المراسلة التقليدية؟

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

void seek(TopicPartition partition, long offset);
void seekToBeginning(Collection < TopicPartition > partitions);

طريقة يطلب() يمكن استخدامها مع الطريقة
offsetsForTimes (خريطة الطوابع الزمنية للبحث) للعودة إلى حالة معينة في وقت ما في الماضي.

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

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

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

توافر عالية

نهج كافكا للتوافر العالي يختلف تمامًا عن نهج ActiveMQ. تم تصميم كافكا حول مجموعات متدرجة حيث تتلقى جميع نسخ الوسيط الرسائل وتوزعها في نفس الوقت.

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

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

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

في الحالة الأساسية ، يتم إنشاء موضوع في كتلة كافكا بالخصائص التالية:

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

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

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

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

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

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

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

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

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

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

نتائج

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

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

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

يتبع ...

يمكن للمستخدمين المسجلين فقط المشاركة في الاستطلاع. تسجيل الدخول، من فضلك.

هل كافكا مستخدم في مؤسستك؟

  • نعم

  • لا

  • مستخدمة سابقا ، الآن لا

  • نحن نخطط لاستخدام

صوت 38 مستخدمين. امتنع 8 مستخدما عن التصويت.

المصدر: www.habr.com

إضافة تعليق