
تم إجراء الاختبار باستخدام Yandex Tank.
تم استخدام Symfony 4 و PHP 7.2 كتطبيق.
كان الهدف هو مقارنة خصائص الخدمات بأحمال مختلفة وإيجاد الخيار الأفضل.
للراحة ، يتم جمع كل شيء في حاويات الإرساء ويتم رفعه باستخدام عامل الإرساء.
تحت القط هناك الكثير من الجداول والرسوم البيانية.
شفرة المصدر هنا .
يجب تنفيذ جميع أمثلة الأوامر الموضحة في المقالة من دليل المشروع.
التطبيق
يعمل التطبيق على Symfony 4 و PHP 7.2.
يجيب عن مسار واحد فقط ويعود:
- رقم عشوائي
- البيئة
- معرف العملية
- اسم الخدمة التي تعمل بها ؛
- متغيرات php.ini.
الإجابة على سبيل المثال:
curl 'http://127.0.0.1:8000/' | python -m json.tool { "env": "prod", "type": "php-fpm", "pid": 8, "random_num": 37264, "php": { "version": "7.2.12", "date.timezone": "Europe/Paris", "display_errors": "", "error_log": "/proc/self/fd/2", "error_reporting": "32767", "log_errors": "1", "memory_limit": "256M", "opcache.enable": "1", "opcache.max_accelerated_files": "20000", "opcache.memory_consumption": "256", "opcache.validate_timestamps": "0", "realpath_cache_size": "4096K", "realpath_cache_ttl": "600", "short_open_tag": "" } }
تم تكوين PHP في كل حاوية:
- يتم تمكين OPcache.
- تكوين ذاكرة التخزين المؤقت bootstrap باستخدام الملحن.
- تتوافق إعدادات php.ini مع أفضل ممارسات Symfony .
سجلات مكتوبة في stderr:
/config/packages/prod/monolog.yaml
monolog: handlers: main: type: stream path: "php://stderr" level: error console: type: console
ذاكرة التخزين المؤقت مكتوبة بـ / dev / shm:
/src/Kernel.php
... class Kernel extends BaseKernel { public function getCacheDir() { if ($this->environment === 'prod') { return '/dev/shm/symfony-app/cache/' . $this->environment; } else { return $this->getProjectDir() . '/var/cache/' . $this->environment; } } } ...
يقوم كل عامل ميناء بإعداد ثلاثة حاويات رئيسية:
- Nginx - الخادم الوكيل العكسي ؛
- التطبيق - أعد رمز التطبيق مع جميع التبعيات.
- PHP FPM \ Nginx Unit \ Road Runner \ React PHP - خادم التطبيق.
تقتصر معالجة الطلب على مثيلين للتطبيق (حسب عدد مراكز المعالج).
الخدمات
مدير عملية PHP. مكتوب في C.
الايجابيات:
- لا حاجة لتتبع الذاكرة ؛
- لا حاجة لتغيير أي شيء في التطبيق.
سلبيات:
- يجب على PHP تهيئة المتغيرات لكل طلب.
أمر تشغيل التطبيق باستخدام عامل التهيئة:
cd docker/php-fpm && docker-compose up -d
مدير عملية PHP. هو مكتوب في PHP.
الايجابيات:
- تهيئة المتغيرات مرة واحدة ثم استخدامها ؛
- لا حاجة لتغيير أي شيء في التطبيق (هناك وحدات جاهزة لـ Symfony / Laravel و Zend و CakePHP).
سلبيات:
- بحاجة إلى متابعة الذاكرة.
أمر تشغيل التطبيق باستخدام عامل التهيئة:
cd docker/php-ppm && docker-compose up -d
خادم التطبيق من فريق Nginx. مكتوب في C.
الايجابيات:
- يمكنك تغيير التكوين باستخدام HTTP API ؛
- يمكنك تشغيل مثيلات متعددة لتطبيق واحد في وقت واحد مع تكوينات مختلفة وإصدارات اللغة ؛
- لا حاجة لتتبع الذاكرة ؛
- لا حاجة لتغيير أي شيء في التطبيق.
سلبيات:
- يجب على PHP تهيئة المتغيرات لكل طلب.
لتمرير متغيرات البيئة من ملف تكوين nginx-unit ، تحتاج إلى إصلاح php.ini:
; Nginx Unit variables_order=E
أمر تشغيل التطبيق باستخدام عامل التهيئة:
cd docker/nginx-unit && docker-compose up -d
مكتبة لبرمجة الحدث. هو مكتوب في PHP.
الايجابيات:
- باستخدام المكتبة ، يمكنك كتابة خادم يقوم بتهيئة المتغيرات مرة واحدة فقط ومواصلة العمل معها.
سلبيات:
- يجب عليك كتابة رمز للخادم ؛
- بحاجة إلى تتبع الذاكرة.
إذا استخدمت علامة --reboot-kernel-after-request للعامل ، فسيتم إعادة تهيئة Symfony Kernel لكل طلب. مع هذا النهج ، لا تحتاج إلى مراقبة الذاكرة.
أمر تشغيل التطبيق باستخدام عامل التهيئة:
cd docker/react-php && docker-compose up -d --scale php=2
خادم الويب ومدير عملية PHP. مكتوب في Golang.
الايجابيات:
- يمكنك كتابة عامل يقوم بتهيئة المتغيرات مرة واحدة فقط ومواصلة العمل معها.
سلبيات:
- يجب عليك كتابة الكود للعامل ؛
- بحاجة إلى تتبع الذاكرة.
إذا استخدمت علامة --reboot-kernel-after-request للعامل ، فسيتم إعادة تهيئة Symfony Kernel لكل طلب. مع هذا النهج ، لا تحتاج إلى مراقبة الذاكرة.
أمر تشغيل التطبيق باستخدام عامل التهيئة:
cd docker/road-runner && docker-compose up -d
اختبار
تم إجراء الاختبار باستخدام Yandex Tank.
كان التطبيق و Yandex Tank على خوادم افتراضية مختلفة.
ميزات الخادم الظاهري مع التطبيق:
الافتراضية : KVM
وحدة المعالجة المركزية : 2 النوى
ذاكرة الوصول العشوائي : 4096 ميغابايت
SSD : 50 جيجابايت
اتصال : 100MBit
نظام التشغيل : CentOS 7 (64x)
الخدمات التي تم اختبارها:
- php-fpm
- php-ppm
- وحدة nginx
- عداء الطريق
- إعادة تشغيل الطريق (مع العلم --reboot-kernel-after-request )
- رد فعل فب
- رد فعل php-reboot (مع العلم --reboot-kernel-after-request )
للاختبارات 1000/10000 rps المضافة خدمة php-fpm-80
تم استخدام تكوين php-fpm لذلك:
pm = dynamic pm.max_children = 80
يحدد Yandex Tank مقدمًا عدد المرات التي يحتاج فيها لإطلاق النار على الهدف ، ولا يتوقف حتى نفاد الخراطيش. اعتمادًا على سرعة استجابة الخدمة ، قد يكون وقت الاختبار أطول من المحدد في تكوين الاختبار. لهذا السبب ، قد يكون لرسومات الخدمات المختلفة أطوال مختلفة. كلما كانت استجابة الخدمة أبطأ ، سيكون الجدول الزمني أطول.
لكل خدمة وتكوين Yandex Tank ، تم إجراء اختبار واحد فقط. بسبب هذا ، قد تكون الأرقام غير دقيقة. كان من المهم تقييم خصائص الخدمات بالنسبة لبعضها البعض.
100 دورة في الدقيقة
فانتوم ياندكس تانك التكوين
phantom: load_profile: load_type: rps schedule: line(1, 100, 60s) const(100, 540s)
تقرير مفصل الروابط
في المئة من زمن الاستجابة
الرصد
الرسوم البيانية

الرسم البياني 1.1 متوسط زمن الاستجابة في الثانية الواحدة

الرسم البياني 1.2 متوسط تحميل المعالج في الثانية

الرسم البياني 1.3 متوسط استهلاك الذاكرة في الثانية الواحدة
500 روبية
فانتوم ياندكس تانك التكوين
phantom: load_profile: load_type: rps schedule: line(1, 500, 60s) const(500, 540s)
تقرير مفصل الروابط
في المئة من زمن الاستجابة
الرصد
الرسوم البيانية

الرسم البياني 2.1 متوسط زمن الاستجابة في الثانية الواحدة

الرسم البياني 2.2 متوسط تحميل المعالج في الثانية

الرسم البياني 2.3 متوسط استهلاك الذاكرة في الثانية الواحدة
1000 روبية
فانتوم ياندكس تانك التكوين
phantom: load_profile: load_type: rps schedule: line(1, 1000, 60s) const(1000, 60s)
تقرير مفصل الروابط
في المئة من زمن الاستجابة
الرصد
الرسوم البيانية

الرسم البياني 3.1 متوسط زمن الاستجابة في الثانية الواحدة

الرسم البياني 3.2 متوسط زمن الاستجابة في الثانية (بدون php-fpm ، php-ppm ، إعادة تشغيل الطريق)

الرسم البياني 3.3 متوسط تحميل المعالج في الثانية

الرسم البياني 3.4 متوسط استهلاك الذاكرة في الثانية الواحدة
10000 دورة في الدقيقة
فانتوم ياندكس تانك التكوين
phantom: load_profile: load_type: rps schedule: line(1, 10000, 30s) const(10000, 30s)
تقرير مفصل الروابط
في المئة من زمن الاستجابة
الرصد

الرسم البياني 4.1 متوسط زمن الاستجابة في الثانية الواحدة

الرسم البياني 4.2 متوسط زمن الاستجابة في الثانية (بدون php-fpm ، php-ppm)

الرسم البياني 4.3 متوسط تحميل المعالج في الثانية

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

الرسم البياني 5.1 95 ٪ المئوية من وقت الاستجابة

الرسم البياني 5.2 95 ٪ من وقت الاستجابة (بدون php-fpm)

الرسم البياني 5.3 تحميل وحدة المعالجة المركزية القصوى

الرسم البياني 5.4 الحد الأقصى لاستهلاك الذاكرة
الحل الأمثل (بدون تغيير الكود) ، في رأيي ، هو مدير عمليات Nginx Unit. إنها تظهر نتائج جيدة في سرعة الاستجابة وتحظى بدعم الشركة.
في أي حال ، يجب تحديد نهج وأدوات التطوير بشكل فردي ، اعتمادًا على أعباء العمل وموارد الخادم وقدرات المطور.
محدث
للاختبارات 1000/10000 rps المضافة خدمة php-fpm-80
تم استخدام تكوين php-fpm لذلك:
pm = dynamic pm.max_children = 80