أنظمة RPC المعيارية (وجسون المقلوبة)


مقارنة بين الأدوات المختلفة (RabbitMQ ، Crossbar.io ، Nats.io ، Nginx ، وما إلى ذلك) لتنظيم RPC بين الخدمات الصغيرة.

استخدام الذاكرة


استخدام وحدة المعالجة المركزية


اختبار متعدد المعالج



تحديث المادة 2019-12-15

ملخص . تنفيذ مكالمات RPC المتزامنة عبر نظام MQ الكلاسيكي ليس فعالًا - فهو يوفر أداءً منخفضًا وآثارًا جانبية تحتاج إلى جرح يدويًا (أو باستخدام أدوات إضافية).
إن Inverted Json هو خادم مهام خفيف الوزن يسمح لك بإجراء مكالمات RPC متزامنة "صادقة" (يتصل العميل والخادم من خلال Inverted Json لإرسال المعلومات) ، مما يضمن الأداء العالي (أسرع 7 مرات من RabbitMQ) ، ويتم الاتصال عبر http ، والذي يسمح لك باستخدام أي أدوات http ، حتى حليقة من وحدة التحكم.

1. الاختبارات


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

2. MQ أو RPC


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

3. RPC على RabbitMQ


غالبًا ما يستخدم RabbitMQ لتنظيم RPCs ، ولكن مثل أنظمة MQ المشابهة ، فإنه ينشئ حملًا إضافيًا ، وهذا هو السبب في أن استخدامه ليس مثمرًا للغاية.

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

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

4. مقلوب Json


هناك العديد من أنظمة MQ المختلفة ، ولكن ليس هناك الكثير من خوادم Job (RPCs) مثل Gearman / Crossbar.io هي خيارات صغيرة جدًا ، لذلك غالباً ما يأخذ المطورون أنظمة MQ لأنظمة RPC.
لذلك ، تم إنشاء مقلوب JSON (iJson) - خادم وكيل بواجهة http حيث يتصل العملاء والعمال كعميل شبكة: [العميل] -> [مقلوب Json] <- [العامل] ، مكتوب في C / C ++ ، يستخدم epoll ، أجهزة الحالة للتوجيه ، محلل تدفق json ، شرائح بدلاً من السلاسل * ، إلخ. طرق لتحسين الأداء.

مزايا JSON المقلوب على RabbitMQ:
  • لا حاجة لتنظيف قنوات العميل والعمال من الرسائل غير المستلمة
  • ليس من الضروري إجراء اختبار ping للعامل ، سيتلقى العميل خطأ على الفور إذا قام العامل بقطع الاتصال (مع اتصال احتياطي)
  • أسهل api - مجرد طلب http (كقاعدة عامة ، يتم دعمه بالفعل من قبل جميع اللغات والأطر)
  • يعمل بشكل أسرع ويستهلك ذاكرة أقل
  • أسهل طريقة لإرسال أوامر إلى عامل معين (على سبيل المثال ، إذا كان هناك العديد من العمال في قائمة الانتظار ، ولكن عليك العمل مع واحد معين)

معلومات أخرى Json مقلوب
  • القدرة على نقل البيانات الثنائية (وليس فقط json ، كما يوحي الاسم)
  • ليس من الضروري تحديد معرّف الهوية إذا كان العامل متصلاً كحافظ على الحياة ، حيث يقوم Inverted Json ببساطة بالربط بين العميل والعامل مباشرة.
  • القدرة على "الاشتراك" في العديد من الأوامر (القنوات) ، والاشتراك في نمط (على سبيل المثال command / *) دون فقدان الأداء.
  • صورة عامل الميناء فقط 2.6 ميغابايت (نسخة ضئيلة)
  • Kernel Inverted Json فقط ~ 1400 سطرًا من التعليمات البرمجية (الإصدار 3.0) ، رمز أقل - أخطاء أقل ؛)
  • لا يقوم JSON المقلوب بتعديل نص الطلب (النص الأساسي) ، ولكنه يرسله كما هو.


5. حاول مقلوب Json في 3 دقائق


يمكنك تجربة Inverted Json الآن إذا كان لديك Docker and curl :


وصف من الصورة:
1) إطلاق صورة عامل ميناء لـ Inverted Json على المنفذ 8001 ، - سجل 47 سجلات الطلبات الواردة ، وما إلى ذلك:
$ docker run -it -p 8001:8001 lega911/ijson --log 47 

2) سجل العامل لمهمة "calc / sum" ، وانتظر المهمة ، اطلب نوع "get" ، أي - احصل على المهمة:
 $ curl localhost/calc/sum -H 'type: get' 

3) يقدم العميل طلب حساب / مبلغ RPC:
 $ curl localhost/calc/sum -d '{"id": 15, "data": "2+3"}' 

4) يتلقى العامل المهمة `{" معرف ": 15 ،" بيانات ":" 2 + 3 "}` - البيانات لم تتغير ، والآن تحتاج إلى إرسال النتيجة إلى نفس المعرف ، ونوع الطلب "النتيجة":
 $ curl localhost -H 'type: result' -d '{"id": 15, "result": 5}' 

... ويحصل العميل على النتيجة كما هي `{"id": 15, "result": 5}`

5.1. JsonRPC


JsonRPC 2 غير مدعوم ، ولكن هناك بعض الأسس ، على سبيل المثال ، يمكن للعميل إرسال طلبات مثل (url / rpc / call):
 {"jsonrpc": "2.0", "method": "calc/sum", "params": [42, 23], "id": 1} 
قبول أخطاء مثل:
 {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": null} 
ومع ذلك ، إذا كان هناك طلب ، فيمكن تحسين دعم JsonRPC.

5.2. العميل بايثون ومثال العامل


 # client.py import requests print(requests.post('http://127.0.0.1:8001/test/command', json={'id': 1, 'params': 'Hello'}).json()) # worker.py import requests while True: req = requests.post('http://127.0.0.1:8001/test/command', headers={'type': 'get'}).json() response = { 'id': req['id'], 'result': req['params'] + ' world!' } requests.post('http://127.0.0.1:8001/', json=response, headers={'type': 'result'}) 

وهنا يمكنك العثور على مثال في "وضع العامل" ، وهو أكثر إنتاجية وصغرًا.

6. بعض الأفكار حول النتيجة المرجعية


  • Crossbar.io : يعتمد على الثعبان ، لذا فهو ليس سريعًا ولا يمكنه استخدام نوى متعددة بسبب GIL.
  • RabbitMQ : RPC أعلى MQ ، الذي يفرض حمولة إضافية. انخفاض سريع في الأداء مع زيادة الحمل (لا ينعكس في الاختبار).
  • ناتس : ليست سيئة ، على الرغم من أدنى من مقلوب Json ، كما سيكون RPC عبر MQ أيضًا نفس المشكلات.
  • مقلوب Json : الوصول إلى حد الشبكة (أي إطلاق عدة نسخ من الاختبارات على مراكز مختلفة لا يعطي نتيجة أفضل في المجموع) ، أظهر الاستخدام الأكثر فعالية للذاكرة والمعالج بالنسبة للأداء.
  • Nginx : عندما يمر الوكيل ، ينخفض ​​الأداء بسرعة إذا لم يتم تشغيل وضع المحافظة على الحياة (إيقاف التشغيل بشكل افتراضي) ، نظرًا لأن نظام التشغيل linux لا يسمح بفتح / إغلاق العديد من المقابس في فترة زمنية قصيرة (لا ينعكس هذا في الاختبار).
  • Trafik : شره جدا ، يستخدم 600 ٪ من وحدة المعالجة المركزية في ذروتها ، أدنى من nginx في السرعة
  • uvloop (تحت asyncio) - يعطي أداء جيد للغاية ، لأن معظم مكتوب في C / C ++ ، ل RPC هو الأفضل من ZeroMQ
  • ZeroMQ - العامل نفسه مكتوب في بيثون ، لذلك واجه النواة ، على الرغم من أن اختبار المعالجات المتعددة يستهلك أكثر من 100 ٪ وحدة المعالجة المركزية ، ويرجع ذلك إلى حقيقة أن zeromq نفسه مكتوب في C / C ++ دون التقاط GIL. إنه يقدم أداءً رائعًا ، ولكن من ناحية أخرى ، إذا لم يكن العامل + أ فقط ب ، فإن أي مضاعفات ستؤدي إلى انخفاض كبير في معدل تكلفة النقرة ، لأن سوف تصل الأساسية حتى في وقت سابق.
  • ZeroRPC : تم إعلانه كغلاف خفيف الوزن على ZeroMQ ، في الواقع ، تم فقد 95٪ من الأداء من ZeroMQ ، يبدو أنه ليس خفيفًا جدًا.
  • GRPC : ينتج خيار بيثون الكثير من كود بيثون المتداول ، أي اتضح أن المعالج ثقيل ويستقر بسرعة على وحدة المعالجة المركزية ، ولربما لا توجد مشكلة من هذا القبيل بالنسبة إلى اللغات المترجمة.
  • اختبارات ثنائية النواة ومتعددة النوى ، في بعض النوى الأساسية انخفضت بعض المؤشرات ، لأن عليك التنافس على موارد وحدة المعالجة المركزية مع رمز اختبار العميل ، من ناحية أخرى ، أعطت بعض الاختبارات أداءً رائعًا ، على سبيل المثال Traefik ، الذي أكل وحدة المعالجة المركزية بنسبة 600٪


7. الخاتمة


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

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

PS:


  • استغرق الأمر وقتًا أطول لإنشاء هذه المقالة بما في ذلك الاختبارات بدلاً من إنشاء مقلوب Json نفسه
  • تم كتابة نماذج Json المقلوبة أيضًا في 1. python + asyncio + uvloop ، 2. في GoLang
  • تمت مراجعة الاختبارات من قبل خبراء مختلفين.
  • "الشرائح بدلاً من الأوتار" - في معظم الحالات ، عند تحليل http / json ، لا يتم نسخ البيانات إلى سلاسل ، ولكن يتم استخدام رابط البيانات المصدر ، وبالتالي ، لا يوجد أي تخصيص ونسخ غير ضروري للذاكرة.
  • إذا كنت ستختبر - لا تستخدم الطلبات في بيثون ، فهي بطيئة للغاية ، أفضل من البيكورل ، يتم استخدام هذا المجمع في الاختبارات.
  • المؤشر هنا
  • المصادر هنا

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


All Articles