اختبار الضغط

ما العوامل التي تؤثر على نتائج اختبار الضغط؟

  • زمن انتقال الشبكة من جهاز الضغط إلى الخادم (يُوصى بإجراء الاختبار على الشبكة الداخلية أو المحلية)
  • عرض النطاق من جهاز الضغط إلى الخادم (يُوصى بإجراء الاختبار على الشبكة الداخلية أو المحلية)
  • هل تم تفعيل HTTP keep-alive (يُوصى بتفعيله)
  • هل عدد التزامنات كافٍ (للاختبار عبر الشبكة الخارجية يُوصى بزيادة التزامن قدر الإمكان)
  • هل عدد عمليات الخادم مناسب (لعمليات helloworld يُوصى بتساوي عدد العمليات مع عدد المعالجات، لعمليات قاعدة البيانات يُوصى بأن يكون أربعة أضعاف المعالجات أو أكثر)
  • أداء العمل نفسه (مثل استخدام قاعدة بيانات خارجية)

ما هو HTTP keep-alive؟

آلية HTTP Keep-Alive هي تقنية تُستخدم لإرسال طلبات واستجابات HTTP متعددة عبر اتصال TCP واحد، ولها تأثير كبير على نتائج اختبار الأداء، وإيقاف keep-alive قد يقلل QPS بشكل كبير.
حالياً المتصفحات تُفعّل keep-alive افتراضياً، أي أن المتصفح يحتفظ بالاتصال مؤقتاً دون إغلاقه بعد زيارة عنوان HTTP، ويعيد استخدامه في الطلب التالي لتحسين الأداء.
يُوصى بتفعيل keep-alive أثناء اختبار الضغط.
علاوة على ذلك، إذا أُجري اختبار الضغط دون تفعيل keep-alive، فإن منافذ العميل المحلية ستُستنفد بسرعة بواسطة الاتصالات في حالة TIME_WAIT، ويتجلى ذلك بطلبات فاشلة عند تجاوز إجمالي الطلبات عتبة معينة (عادة حوالي 28.000).

كيف تُفعّل HTTP keep-alive أثناء اختبار الضغط؟

إذا استُخدم برنامج ab للاختبار فيُضاف المعامل -k، مثل ab -n100000 -c200 -k http://127.0.0.1:8787/.
apipost يحتاج لإرجاع رأس gzip في الاستجابة لتتمكن من تفعيل keep-alive (خلل في apipost، انظر أدناه).
برامج اختبار الضغط الأخرى تُفعِّل ذلك افتراضياً عادة.

لماذا يكون QPS منخفضاً جداً عند الاختبار عبر الشبكة الخارجية؟

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

لماذا ينخفض الأداء بعد المرور عبر وكيل nginx؟

تشغيل nginx يستهلك موارد النظام، والتواصل بين nginx و webman يستهلك موارداً أيضاً.
بما أن موارد النظام محدودة، ولا يستطيع webman الحصول على كل الموارد، فمن الطبيعي أن ينخفض أداء النظام ككل.
لتقليل تأثير وكيل nginx على الأداء قدر الإمكان، يُنصح بإيقاف سجلات nginx (access_log off;) وتفعيل keep-alive بين nginx و webman، انظر وكيل nginx.
كما أن https يستهلك موارداً أكثر من http لأن https يتطلب مصافحة SSL/TLS وتشفير وفك تشفير البيانات وحجم رزم أكبر يشغل عرض نطاقاً أكثر، مما يؤدي لانخفاض الأداء.
إذا استُخدمت اتصالات قصيرة (بدون تفعيل HTTP keep-alive) في اختبار الضغط، فكل طلب يحتاج اتصال SSL/TLS إضافي، وسينخفض الأداء بشدة. يُوصى بتفعيل HTTP keep-alive عند اختبار https.

كيف نعرف أن النظام وصل لحد الأداء؟

عادة عند وصول CPU إلى 100% يكون النظام قد بلغ حد الأداء. إن كان CPU ما زال خالياً فلم يبلغ الحد بعد، ويمكن زيادة التزامن لرفع QPS.
إن لم ترفع زيادة التزامن QPS فقد يكون عدد عمليات webman غير كافٍ، يُرجى زيادتها. إن لم يتحسن الأمر فتأكد من كفاية عرض النطاق.

لماذا تظهر نتائج اختباري أن أداء webman أقل من إطار عمل gin في Go؟

techempower يوضح أن webman يتفوق على gin بنحو الضعف في كل المؤشرات (نص عادي، استعلام قاعدة بيانات، تحديث قاعدة البيانات).
إن اختلفت نتائجك فقد يكون بسبب استخدام ORM في webman مما يسبب فقدان أداء كبير، جرّب مقارنة webman+PDO الأصلي مع gin+SQL الأصلي.

ما مقدار فقدان الأداء عند استخدام ORM في webman؟

فيما يلي مجموعة بيانات اختبار:

البيئة
خادم Alibaba Cloud 4 أنوية 4G، قاعدة بيانات MySQL محلية، استعلام عشوائي لسجل واحد من 100.000 وإرجاع JSON، اختبار ضغط محلي.

إذا استُخدم PDO الأصلي
QPS لـ webman 17.800

إذا استُخدم Db::table() من Laravel
QPS لـ webman ينخفض إلى 9.400

إذا استُخدم Model من Laravel
QPS لـ webman ينخفض إلى 7.200

نتائج thinkORM مشابهة، لا فرق يذكر.

تنبيه
رغم أن استخدام ORM يقلل الأداء، إلا أن الأداء كافٍ ومُفيض لـ 99% من الأعمال. إن كنت ضمن الـ 1% المتبقية فيُحلّ بسهولة بإضافة CPU أو خوادم.
يجب إيجاد توازن بين كفاءة التطوير والقابلية للصيانة والأداء بدلاً من السعي الأعمى للأداء وحده.

لماذا يكون QPS منخفضاً جداً عند اختبار الضغط بـ apipost؟

وحدة اختبار الضغط في apipost تحتوي على خلل: إن لم يُرجع الخادم رأس gzip لا يمكن الحفاظ على keep-alive، مما يخفض الأداء بشدة.
الحل: ضغط البيانات وإضافة رأس gzip عند الإرجاع، مثل:

<?php
namespace app\controller;
class IndexController
{
    public function index()
    {
        return response(gzencode('hello webman'))->withHeader('Content-Encoding', 'gzip');
    }
}

بالإضافة إلى ذلك، apipost في بعض الحالات لا يستطيع توليد ضغط كافٍ، إذ يعطي QPS أقل من ab بنحو 50% عند نفس التزامن.
يُوصى باستخدام ab أو wrk أو برامج اختبار ضغط احترافية أخرى بدلاً من apipost.

ضبط عدد العمليات المناسب

webman يفتح افتراضياً عدد عمليات يساوي cpu*4. في واقع الأمر لعمليات helloworld بدون إدخال/إخراج شبكي، فالأفضل أن يكون عدد العمليات مساوياً لعدد أنوية المعالج لتقليل تكلفة تبديل العمليات.
للعمليات ذات الإدخال/الإخراج الحاصر مثل قاعدة البيانات و redis، فيُضبط عدد العمليات بين 3–8 أضعاف المعالج، لأن زيادة التزامن تحتاج المزيد من العمليات، وتكلفة تبديل العمليات تُهمَل مقارنة بالإدخال/الإخراج الحاصر.

نطاقات مرجعية لاختبار الضغط

خادم سحابي 4 أنوية 4G 16 عملية اختبار محلي/شبكة داخلية

- keep-alive مفعّل keep-alive غير مفعّل
hello world 80.000–160.000 QPS 10.000–30.000 QPS
استعلام قاعدة بيانات واحد 10.000–20.000 QPS 10.000 QPS

بيانات اختبار techempower من طرف ثالث

أمثلة أوامر اختبار الضغط

ab

# 100000 طلب 200 تزامن keep-alive مفعّل
ab -n100000 -c200 -k http://127.0.0.1:8787/

# 100000 طلب 200 تزامن keep-alive غير مفعّل
ab -n100000 -c200 http://127.0.0.1:8787/

wrk

# 200 تزامن اختبار ضغط 10 ثوانٍ keep-alive مفعّل (افتراضي)
wrk -c 200 -d 10s http://example.com