هذه المقالة ترجمة لمقال كيفن غولدبيرغ "تحليل أداء خوادم Python WSGI: الجزء الثاني" dzone.com/articles/a-performance-analysis-of-python-wsgi-servers-part مع بعض الإضافات من المترجم.
مقدمة
في
الجزء الأول من هذه السلسلة ، قابلت
WSGI والخوادم الستة الأكثر شيوعًا وفقًا لمؤلف
WSGI . في هذا الجزء ، سيتم عرض نتيجة تحليل أداء هذه الخوادم. لهذا الغرض ، تم إنشاء وضع حماية اختبار خاص.
المتسابقون
نظرًا لضيق الوقت ، اقتصر البحث على ستة خوادم WSGI.
يتم استضافة جميع تعليمات بدء التشغيل لهذا المشروع
على GitHub . ربما بمرور الوقت ، سيتوسع المشروع وسيتم تقديم تحليلات الأداء لخوادم WSGI الأخرى. ولكن في الوقت الحالي ، سنتحدث عن ستة خوادم:
- يصف Bjoern نفسه بأنه "خادم WSGI فائق السرعة" ويفتخر بأنه "خادم WSGI الأسرع والأصغر والأخف وزنًا". أنشأنا تطبيقًا صغيرًا يستخدم معظم إعدادات المكتبة الافتراضية.
- CherryPy هو إطار عمل شائع ومستقر للغاية وخادم WSGI. تم استخدام هذا البرنامج النصي الصغير لخدمة عينة التطبيق من خلال CherryPy .
- تم استلهام Gunicorn من خادم Ruby Unicorn (ومن هنا جاء الاسم). ويدعي بتواضع أنه "يتم تنفيذه ببساطة ، وسهل الاستخدام وسريع إلى حد ما". بخلاف Bjoern و CherryPy ، Gunicorn هو خادم مستقل. قمنا بإنشائه باستخدام هذا الأمر . تم تعيين المعلمة "WORKER_COUNT" على ضعف عدد نوى المعالج المتاحة ، بالإضافة إلى واحد. تم ذلك بناءً على توصيات من وثائق Gunicorn .
- Meinheld هو خادم ويب متوافق مع WSGI عالي الأداء يدعي أنه خفيف الوزن. بناءً على المثال الموضح على موقع الخادم ، أنشأنا تطبيقنا .
- تم إنشاء mod_wsgi من قبل نفس الخالق مثل mod_python . مثل mod_python ، يتوفر فقط لـ Apache. ومع ذلك ، فإنه يتضمن أداة تسمى "mod_wsgi express" التي تنشئ أصغر مثيل ممكن لأباتشي. قمنا بتكوين واستخدام mod_wsgi express باستخدام هذا الأمر . لمطابقة Gunicorn ، قمنا بضبط mod_wsgi لإنشاء ضعف عدد العاملين مثل نوى المعالج.
- uWSGI هو خادم تطبيقات كامل الميزات . عادة ، يتم إقران uWSGI مع خادم وكيل (على سبيل المثال: Nginx). ومع ذلك ، من أجل تقييم أداء كل خادم بشكل أفضل ، حاولنا استخدام الخوادم العارية فقط وأنشأنا عاملين لكل نواة معالج متوفرة.
المعيار
لجعل الاختبار موضوعيًا قدر الإمكان ، تم إنشاء حاوية
Docker لعزل الخادم قيد الاختبار عن بقية النظام. أيضًا ، تضمن استخدام حاوية Docker أن يبدأ كل إطلاق من نقطة الصفر.
الخادم:
- معزولة في حاوية عامل ميناء.
- 2 نوى معالج مخصصة.
- كانت ذاكرة الوصول العشوائي للحاوية محدودة 512 ميجابايت.
الاختبار:
- أجرت wrk ، وهي أداة حديثة لقياس أداء HTTP ، اختبارات.
- تم اختبار الخوادم بترتيب عشوائي مع زيادة في عدد الاتصالات المتزامنة في النطاق من 100 إلى 10000.
- يقتصر wrk على نواتين لوحدة المعالجة المركزية لا يستخدمهما Docker.
- استمر كل اختبار 30 ثانية وتكرر 4 مرات.
المقياس:
- تم توفير متوسط عدد الطلبات والأخطاء والتأخيرات المستمرة بواسطة wrk .
- وأظهرت المراقبة المدمجة في Docker مستويات استخدام وحدة المعالجة المركزية وذاكرة الوصول العشوائي.
- تم تجاهل أعلى وأدنى قراءات ، وتم حساب القيم المتبقية.
- للفضول ، أرسلنا النص الكامل إلى GitHub .
النتائج
تم تضمين جميع مؤشرات الأداء الأولية
في مستودع المشروع ، كما
تم توفير
ملف CSV موجز. أيضًا ، من أجل التصور ، تم إنشاء الرسومات في بيئة
مستندات Google .
RPS مقابل عدد الاتصالات المتزامنة
يوضح هذا الرسم البياني متوسط عدد الطلبات المتزامنة ؛ كلما زاد الرقم ، كان ذلك أفضل.


- بجورن: فائز واضح.
- CherryPy: على الرغم من كتابته بلغة Python الخالصة ، فقد كان الأفضل أداءً.
- Meinheld: أداء ممتاز نظرًا لموارد الحاويات النادرة.
- mod_wsgi: ليس الأسرع ، لكن الأداء كان متسقًا وكافًا.
- Gunicorn: أداء جيد في الأحمال المنخفضة ، ولكن هناك معركة مع عدد كبير من الاتصالات.
- uWSGI: محبط نتيجة النتائج السيئة.
الفائز: بجورنبجورن
من خلال عدد الطلبات المستمرة ،
Bjoern هو الفائز الواضح. ومع ذلك ، نظرًا لأن الأرقام أعلى بكثير من تلك الخاصة بالمنافسين ، فنحن متشككون قليلاً. لسنا متأكدين من أن
Bjoern سريع للغاية حقًا. في البداية اختبرنا الخوادم أبجديًا ، واعتقدنا أن
بجورن حصل على ميزة غير عادلة. ومع ذلك ، حتى بعد بدء تشغيل الخوادم بترتيب خادم عشوائي وإعادة الاختبار ، تظل النتيجة كما هي.
UWSGI
شعرنا بخيبة أمل من النتائج الضعيفة لـ
UWSGI . توقعنا أن يكون في الصدارة. أثناء الاختبار ، لاحظنا أن سجلات
uWSGI تطبع على الشاشة ، وفي البداية أوضحنا نقص الأداء مع العمل الإضافي الذي قام به الخادم. ومع ذلك ، حتى بعد
إضافة خيار "
- تعطيل التسجيل " ، لا يزال
uWSGI هو أبطأ خادم.
كما هو مذكور في دليل
uWSGI ، فإنه عادةً ما يتفاعل مع خادم وكيل مثل Nginx. ومع ذلك ، لسنا متأكدين من أن هذا يمكن أن يفسر مثل هذا الاختلاف الكبير.
تأخير
التأخير هو مقدار الوقت المنقضي بين الطلب واستجابته. الأرقام الأقل أفضل.

- CherryPy: تعامل مع الحمل بشكل جيد.
- بجورن: زمن انتقال منخفض بشكل عام ، ولكنه يعمل بشكل أفضل مع عدد أقل من الاتصالات المتزامنة.
- Gunicorn: جيد ومتسق.
- mod_wsgi: متوسط الأداء ، حتى مع وجود عدد كبير من الاتصالات المتزامنة.
- Meinheld: أداء مقبول بشكل عام.
- uWSGI: uWSGI مرة أخرى في المركز الأخير.
الفائز: CherryPyاستخدام ذاكرة الوصول العشوائي
يوضح هذا المقياس متطلبات الذاكرة و "الخفة" لكل خادم. الأرقام الأقل أفضل.

- بجورن: خفيف للغاية. يستخدم فقط 9 ميغابايت من ذاكرة الوصول العشوائي لمعالجة 10000 الطلبات المتزامنة.
- Meinheld: نفس Bjoern .
- Gunicorn: تتواءم بمهارة مع الأحمال العالية مع استهلاك الذاكرة بالكاد الملحوظ.
- CherryPy: في البداية كانت بحاجة إلى كمية صغيرة من ذاكرة الوصول العشوائي ، ولكن استخدامها زاد بسرعة مع زيادة الحمل.
- mod_wsgi: في المستويات الدنيا ، كانت واحدة من الأكثر كثافة في الذاكرة ، لكنها ظلت متسقة إلى حد ما.
- uWSGI: من الواضح أن الإصدار الذي نختبره به مشكلات في مقدار الذاكرة المستهلكة.
الفائزون: بجورن ومينهولدعدد الأخطاء
يحدث خطأ عند تعطل الخادم أو انقطاعه أو انتهاء مهلة الطلب. كلما كان ذلك أفضل كلما كان ذلك أفضل.

لكل خادم ، قمنا بحساب نسبة النسبة الإجمالية لعدد الطلبات إلى عدد الأخطاء:
- CherryPy: معدل الخطأ حوالي 0 ، حتى مع وجود عدد كبير من الاتصالات.
- بجورن: حدثت أخطاء ، ولكن تم تعويض ذلك بعدد الطلبات التي تمت معالجتها.
- mod_wsgi: يعمل بشكل جيد مع معدل خطأ مقبول يبلغ 6٪.
- Gunicorn: يعمل بمعدل خطأ 9 بالمائة.
- uWSGI: نظرًا للعدد المنخفض من الطلبات التي تم تقديمها ، انتهى الأمر بمعدل خطأ بنسبة 34 بالمائة.
- Meinheld: سقط في الأحمال الأعلى ، وألقى بأكثر من 10000 خطأ أثناء الاختبار الأكثر تطلبًا.
الفائز: CherryPyاستخدام وحدة المعالجة المركزية
الاستخدام العالي لوحدة المعالجة المركزية ليس جيدًا أو سيئًا إذا كان الخادم يعمل بشكل جيد. ومع ذلك ، يوفر هذا بعض المعلومات المثيرة للاهتمام حول الخادم. منذ استخدام نواتين لوحدة المعالجة المركزية ، فإن أقصى استخدام ممكن هو 200 بالمائة.

- Bjoern: خادم أحادي الخيوط ، كما يتضح من استخدامه المتناسق لوحدة المعالجة المركزية بنسبة 100٪.
- CherryPy: متعدد مؤشرات الترابط ، لكنه عالق عند 150 بالمائة. قد يكون هذا بسبب Python GIL .
- Gunicorn: يستخدم العديد من العمليات مع الاستخدام الكامل لموارد وحدة المعالجة المركزية في المستويات الدنيا.
- Meinheld: خادم أحادي الخيوط يستخدم موارد وحدة المعالجة المركزية مثل Bjoern.
- mod_wsgi: خادم متعدد الخيوط يستخدم جميع نوى وحدة المعالجة المركزية في جميع القياسات
- uWSGI: استخدام CPU منخفض جدًا. لا يتجاوز استهلاك وحدة المعالجة المركزية 50 بالمائة. هذا دليل على أن uWSGI لم يتم تكوينه بشكل صحيح.
الفائز: لا ، لأن هذه ملاحظة سلوكية أكثر من كونها مقارنة في الأداء.الخلاصة
لتلخيص! إليك بعض الأفكار العامة التي يمكنك استخلاصها من نتائج كل خادم:
- Bjoern: تبرر نفسها على أنها "خادم WSGI فائق السرعة وخفيف الوزن."
- CherryPy: أداء عالي واستهلاك منخفض للذاكرة ومعدلات خطأ منخفضة. ليس سيئا لبيثون النقي.
- Gunicorn: خادم جيد للأحمال المتوسطة.
- Meinheld: يعمل بشكل جيد ويتطلب الحد الأدنى من الموارد. ومع ذلك ، تكافح مع حمولات أعلى.
- mod_wsgi: يتكامل مع Apache ويعمل بشكل رائع.
- uWSGI: بخيبة أمل كبيرة. إما أننا قمنا بتكوين uWSGI بشكل غير صحيح ، أو أن الإصدار الذي قمنا بتثبيته يحتوي على أخطاء أساسية.