كيف تُحسِّن أداء خادوم Nginx


محمد أحمد العيل

مقدِّمة

يُشكّل خادوم Nginx، السّريع والخفيف، بديلًا - في حالات عديدة - لخادوم Apache كثيرِ المُتطلّبات. كأيّ برنامج آخر، يحتاج Nginx إلى ضبطه من أجل الحصول على أداء أفضل.

مُتطلَّبات الدّرس

ضبط متغيّرَيْ worker_processes و worker_connections

أوّل متغيِّريْن يجب علينا ضبطُهما هما متغيّرا worker_processes و worker_connections. يجب أن نفهم ما الّذي يتحكّم فيه كل واحد من هذيْن المتغيّريْن، قبل الدّخول في تفاصيل إعداد كلّ واحد منهما.

نبدأ بتعليمة worker_processes الّتي تُمثِّل العمود الفقري الصّلب بالنّسبة ل Nginx. تُعطي هذه التّعليمة عددَ العمليّات Processes الّتي يجب على Nginx إنشاؤُها بعد معرفته لعنوان IP والمنافِذ Ports الّتي سيشتغل عليها، وهيّ المسؤولة عن كل ما يُؤدّيه خادوم الويب. يُطلَق على كل واحدة من هذه العمليّات اسم Worker (العامِل). من المُستحسَن تشغيلُ عامل واحد على كل نواة Core من وحدة المُعالجة المركزيّة Central processing unit, CPU. لن ينتُج عن تشغيل أكثر من عامل على نواةٍ ضررٌ كبير على النِّظام لكنّه سيؤدّي إلى وجود العديد من العمليّات السّاكنة Idle processes غير الضّروريّة.

ملحوظة: عمليّة ساكنة هي عمليّة لا تجد ما تفعله ولا تتولّى الإجابة عن أيّ طلب.

يكفي، لمعرفة قيمة worker_processes الأمثل لإعدادك، إلقاءُ نظرة على عدد الأنويّة لديك. يُمكِنك عبر الأمر التّالي الحصول على هذه المعلومة:

grep processor /proc/cpuinfo | wc -l

فلنفترِض أنّ نتيجةَ تنفيذ الأمر هيّ 1. يعني هذا أنّه يوجد في النّظام لدينا نواةٌ واحدة.

المُتغيّر الثّاني worker_connections يُعطي عددَ الاتّصالات الّتي يُمكن لعمليّات من نوع Worker الاستجابة لها في نفس الوقت. القيمة الافتراضيّة هي 768.في العادة، يُرسِل متصفّح الويب طلبيْن - على الأقل - في نفس الوقت إلى الخادوم، وهو ما يعني أنّ عدد العملاء الّذين يُمكِن الرّد عليهم في نفس الوقت يبلغ في أعلى تقدير نصفَ قيمةِ المُتغيِّر worker_connections. من أجل الرّفع من عدد العُملاء المُتّصلين في آنٍ معًا سنُعطي لهذا المُتغيِّر أعلى قيمة تسمح بها موارد الجهاز، والّتي يُمكِن معرفتها عن طريق الأمر:

ulimit -n

ستتغيَّر النّتيجة حسب الجهاز والموارد المُتوفّرة له. نأخذ مثالًا بجهاز ذي إمكانيّات محدودة حيثُ تُساوي هذه القيمة 1024.

نُحدِّث إعدادات Nginx عبر فتح ملفّ الإعداد nginx.conf وتحريره:

sudo nano /etc/nginx/nginx.conf

نُعطي القيمة 1 لـ worker_processes والقيمة 1024 لـworker_connections:

worker_processes 1;
worker_connections 1024;

يجب الانتباه هنا إلى أنّ عدد الاتّصالات الكلّي الّتي يقبله Nginx في نفس الوقت يُساوي جداءَ قيمتَيْ المُتغيّريْن worker_processes و worker_connections. أي، في حال التزمنا بالقاعدة السّابقة، عددَ الأنويّة مضروبًا بعدد الاتّصالات الّتي يُمكن لكل عامِل الاستجابة لها. في مثالنا هنا النّتيجة هيّ 1024 (حاصل ضرب 1024 ب 1). يوجد أيضًا مُتغيِّر keepalive_timeout والّذي يُمكن لقيمته أن تُقلِّلَ من عدد الاتّصالات الفعليّة (سنتطرّق لهذا المتغيِّر).

الصُّّوَّانات Buffers

يُمكِن أن ينتُج عن تعديل حجم الصِّوان (وهي منطقة تخزين مُؤقّت ضمن ذاكرة الوصول العشوائي RAM، تُستخدم لنقل البيانات بين العمليّات) تغيّرات مُعتبرة في الأداء. إذا كان حجم الصِّوان صغيرًا فإن Nginx سيحتاج إلى إنشاء ملفّ تخزين مؤقَّت Temporary file ممّا يُؤدّي إلى كثرة القراءة والكِتابة من القرص الصّلب. توجد بعض التّعليمات الّتي نحتاج لفهمها قبل إجراء أيّ تعديل.

  • client_body_buffer_size: حجم صِوان العميل Client (وحدة الحجم في كامل ملف الإعداد هيّ البايت Byte، يُشير حرف K إلى كيلوبايت KB) أي حجم الجسم Body في طلب Http أثناء إجراء POST. تُستخدَم إجراءات POST أساسًا عند إرسال النّماذج

  • client_header_buffer_size: مُشابهة للتّعليمة السّابقة، ولكن لحجم التّرويسة Header في طلب Http. حجم 1KB مناسِب - غالبًا - لهذه التّعليمة.

  • client_max_body_size: الحجم الأقصى المسموح به لطلب العميل. إذا تجاوز طلب العميل هذا الحجم فإن خادوم ويب Nginx سيُجيب بخطأ 413 (محتوى الطّلب أكبر من المسموح به Request Entity Too Large).

  • large_client_header_buffers: العدد الأعلى والحجم الأقصى للصُّوّان بالنّسبة للتّرويسات العريضة في طلب العميل. في حال كان سطر الطّلب أكبر من حجم الصِّوّان فإن خادوم الويب يُجيب بخطأ 414 (مسار URI للطّلب أطول من المسموح به Request URI too large). نفس الشّيء بالنّسبة للتّرويسة في الطّلب إذ لا يجوز أن تتجاوز حجم الصِّوان المسموح به في هذه التّعليمة وإلاّ فإنّ Nginx سيُجيب بخطأ 400 (طلب غير صالح Bad request). يُشير العدد في هذه التّعليمة إلى العدد الأعلى من الطّلبات ذات التّرويسة العريضة (أي ترويسة بحجم أكبر من المُحدَّد في client_header_buffer_size) المسموح بها.

مثال على قِيّم للمتغيّرات السّابق ذكرها:

client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;

المُهَل Timeouts

المُهل هي مُتغيّرات أخرى تُوّثّر كثيرًا على أداء Nginx.

تُحدّد تعليمتَا client_body_timeout و client_header_timeout المهلة الزّمنيّة (بالثّانيّة) الّتي ينتظرها الخادوم لتلقي محتوى أو ترويسة العميل على التّوالي بعدَ استلام الطّلب منه. إن لم يتلقَّ الخادوم واحدًا من الاثنيْن خلال هذه الفترة فسيُجيب بخطأ 408 (انتهَت مُهلة الطّلب Request time out).

أمّا تعليمة keepalive_timeout فتُحدّد المهلة الزمنيّة لاتّصالات استمرار النّشاط Keep-alive connections. بعبارة أخرى، سيقطع Nginx الاتّصال بعد انقضاء هذه المُهلة بغض النّظر عمّا يُريد العميل.

توجد أيضًا send_timeout والّتي تُعنى بالفترة الزّمنية بين عمليّتَيْ قراءة من طرف العميل. إنْ لم يُرسِل العميل أيّ طلب خلال هذه المهلة فسيقطع خادوم الويب الاتّصالَ به، دون اعتبار لقيمة التّعليمة السّابقة.

مثال على قيّم لمتغيّرات المُهَل الزّمنيّة:

client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;

الضّغط Compression بواسطة Gzip

يُمكِن لأداة الضّغط وفكّ الضّغط Gzip المُساعدة في تحسين أداء خادوم الويب عبر التّقليل من حجم البيانات المُتبادلة؛ لكن ينبغي الحذر من رفع قيمة مستوى الضّغط gzip_comp_level لمستوى عالٍ إذ يُمكن أن يُسبّب ذلك كثرة نشاط أنويّة المُعالج.

لتفعيل الضّغط نُعطي القيمة on لتعليمة gzip. تعليمة gzip_min_length تُحدِّد الحجم الأدنى لتفعيل الضّغط، أي أنّ ملفًّا بحجم أقل من قيمة هذه التّعليمة لن يخضع للضّغط. يُمكِن تحديد صيّغ الملفّات الّتي يُطبَّق عليها الضّغط عبر التّعليمة gzip_type. توجد أيضًا تعليمة gzip_proxied لتعيين طريق التّعامل مع الطّلبات الواردة من عملاء يمرّون عبر وسيط Proxy.

gzip on;
gzip_comp_level 2;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/x-javascript text/xml text/css application/xml;

التّخزين المؤقت للملفات السّاكنة  Static File Caching

يُساهم طلب التّخزين المُوقّت من جانب العميل (المُتصفِّح) في التّقليل من تبادل البيانات والحفاظ على موارد الخادوم. يجب إدراج هذه التّعليمة على مُستوى كُتلة الخادوم Server block ضمن الملف الافتراضي لإعداد كُتلة خادوم Nginx، كما في المثال أدناه. عمل التّعليمة يتمثّل في إخبار العميل بالاحتفاظ بنسخة من الملفّ وعدم تنزيلها من الخادوم طوال مدّة محدّدَة (365 يومًا في المثال). إن احتاج العميل لأحد هذه الملفّات خلال هذه المدّة فسيلجأ للنّسخة الموجودة لديه ولن يتبادل بيانات مع الخادوم.

تُذكَر في التّعليمة أنواع الملفّات الّتي يُطلَب من العميل تخزينها (أساسًا صوّر وملفاّت تنسيق css وjs).

location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}

تعطيل حفظ السّجلّات Logging

يحتفظ Nginx في الإعددات الافتراضية بكلّ طلب يصل إلى الخادوم ضمن ملفّ للسّجلّات Logs. يُمكنك إيقاف هذه الخاصيّة إذا كنتَ تستخدِم أداةً لتحليل المواقع عن طريق إعطاء القيمة off للتّعليمة access_log كما هوّ موضَّح أدناه:

access_log off;

أعِد تشغيل خادوم الويب بعد حفظ ملفّ الإعداد حتى تُؤخذ التّعديلات في الحسبان:

sudo service nginx restart

خاتمة

خادوم ويب مضبوط جيّدًا هو خادوم مُعد ومُهيَّأ ليتصرّف حسب نوعيّة الطّلبات الّتي ترده. ينبغي الانتباه إلى أنّه لا توجد قيمة مُثلى لا ينبغي المساسُ بها لأيّ من المتغيّرات والتّعليمات المذكورة في هذا الدّليل. يجب ضبط الإعدادات حسب كلّ حالة وما يُناسبها.

إذا أردتَ الاستمرار في طريق التّحسين فيُمكنك تجربة التّوسّع الأفقي Horizontal scaling وتوزيع الحِمل Load balancing. الإعدادات المذكورة في هذا الدّليل ليست سوى بداية في الطّريق إلى تحسينات أكبر.

ترجمة – وبتصرّف – للمقال How To Optimize Nginx Configuration





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن