موازنة الحمل مع Nginx
موازنة الحمل مع Nginx
عندما يعجز خادم تطبيق واحد عن مواكبة حجم الطلبات — أو حين تحتاج إلى نشر بلا توقف مع تحمّل الأعطال — تضيف خوادم إضافية وتضع موازن حمل أمامها. يؤدي Nginx هذه المهمة ببراعة في نفس العملية التي تنهي فيها TLS وتخدم ملفاتك الثابتة. فهم خوارزميات upstream وآليات الفحص الصحي وخيارات تثبيت الجلسات هو الفارق بين موازن حمل يعمل في بيئة التجربة وآخر يصمد أمام حركة مرور يوم الجمعة السوداء.
كتلة upstream
كل شيء يبدأ بكتلة upstream. تسمّي المجموعة، وتُدرج الخوادم، وتختار الخوارزمية، ثم توجّه بـ proxy_pass إلى اسم تلك المجموعة من أي كتلة location.
proxy_http_version 1.1 وأفرغ Connection. الإصدار HTTP/1.0 (الافتراضي) يغلق اتصال TCP بعد كل طلب. HTTP/1.1 مع رأس Connection فارغ يأمر Nginx بإبقاء الاتصال مع upstream حياً لإعادة استخدام المقابس عبر الطلبات اللاحقة — مما يُحدث فارقاً كبيراً في الإنتاجية على نطاق واسع.خوارزميات موازنة Upstream
تأتي النسخة المفتوحة من Nginx مع أربع خوارزميات. تضيف Nginx Plus المزيد (least_time وrandom مع خيارَين وzone-aware). اختر بناءً على طبيعة حمل عملك:
- round-robin (الافتراضي) — يذهب كل طلب جديد إلى الخادم التالي في القائمة دورياً بالتساوي. يعمل بشكل جيد حين تكون الطلبات متجانسة في التكلفة والخوادم متطابقة. أضف معامل
weightلتوجيه نسبة أكبر نحو العقد الأقوى. - least_conn — يذهب الطلب الجديد إلى الخادم الذي لديه أقل اتصالات نشطة. الخيار الصحيح للاتصالات طويلة الأمد (WebSockets، البث، استعلامات قواعد البيانات البطيئة) حيث تُراكم round-robin الطلبات على خادم واحد بينما تجلس الأخرى خاملة.
- ip_hash — يحسب hash على IP العميل (أول ثلاثة أوكتيتات لـ IPv4) ويوجّه ذلك العميل دائماً إلى نفس upstream. شكل أساسي من الجلسات اللاصقة بدون ملفات تعريف ارتباط إضافية. ينكسر عندما يكون العملاء خلف NAT مشترك أو CDN.
- hash $variable [consistent] — Hash على أي متغير Nginx: URI، قيمة cookie، رأس طلب. مع
consistentيستخدم حلقة hash متسقة (Ketama) بحيث تضيف أو تزيل خادماً يعيد تعيين جزء صغير فقط من المفاتيح — مفيد للتوكيل إلى ذاكرات تخزين مؤقت upstream.
الفحوصات الصحية السلبية
يُجري Nginx المفتوح فحوصات صحية سلبية: يراقب حركة المرور الحية ويُعلّم الخادم على أنه غير صحي فقط بعد أن يفشل في طلبات حقيقية. المعاملات الرئيسية تعيش في توجيه الخادم داخل upstream:
max_fails=3— عدد الإخفاقات المتتالية قبل اعتبار الخادم معطلاً (الافتراضي 1).fail_timeout=30s— مدة إيقاف الطلبات بعد الوصول للحد الأقصى، وأيضاً النافزة الزمنية التي تُحسب فيهاmax_fails(الافتراضي 10 ثوانٍ).
proxy_next_upstream. بدونه تصل استجابة 502 من backend يتعطل مباشرة للمستخدم. بوجوده يُعيد Nginx المحاولة بشفافية على خادم آخر. قيّد المحاولات بالطلبات غير المتغيّرة أو كن حذراً: إعادة محاولة POST التزم بقاعدة البيانات ستضاعف الكتابة.الفحوصات الصحية النشطة (Nginx Plus / OpenResty / وحدة فحص Upstream)
الفحوصات السلبية تكتشف الإخفاقات فقط على حركة المرور الحية. الفحوصات النشطة تختبر upstreams على فترات في الخلفية، فيُزال الخادم من الدوران قبل أن يصطدم به المستخدم. في Nginx المفتوح تحقق هذا بـ ngx_http_upstream_check_module (مُدمج وقت الترجمة) أو بأدوات مثل Consul + consul-template لإعادة كتابة كتلة upstream. توفره Nginx Plus بشكل أصلي عبر توجيه health_check:
الجلسات اللاصقة
التطبيقات عديمة الحالة — حيث يمكن لأي خادم معالجة أي طلب — هي الأفضل دائماً في التصميم السحابي الأصلي. لكن التطبيقات القديمة كثيراً ما تخزّن بيانات الجلسة في ذاكرة العملية، مما يجعل توجيه العميل لنفس الخادم دائماً أمراً إلزامياً. يوضح الرسم البياني أدناه النموذجين:
توفر Nginx Plus توجيه sticky cookie. في Nginx المفتوح تستخدم ip_hash أو hash على قيمة cookie مستخرجة بـ $cookie_sessionid:
Keepalive للـ Upstream وتجميع الاتصالات
بالنسبة للخدمات عالية الإنتاجية، تتراكم تكلفة بناء اتصالات TCP. توجيه keepalive في كتلة upstream يأمر Nginx بتخزين مجموعة من الاتصالات الخاملة لكل upstream وإعادة استخدامها عبر الطلبات. هذا مختلف عن keepalive للعميل ويُقلل الكمون بشكل كبير على الخدمات التي تُجري آلاف الطلبات في الثانية.
مراقبة سلوك موازن الحمل
وحدة stub_status في Nginx تعرض صفحة حالة بسيطة. للحصول على مقاييس أكثر تفصيلاً على مستوى upstream — الاتصالات النشطة لكل خادم، الحالة الصحية، الطلبات الموجَّهة — تحتاج Nginx Plus أو وحدة طرف ثالث مثل nginx-module-vts. في الإنتاج، تُرسل معظم الفرق سجلات Nginx إلى خط معالجة المقاييس (Prometheus + nginx-prometheus-exporter أو Datadog) وتُنبّه على معدلات 5xx للـ upstream وبيرسنتيلات وقت الاستجابة بدلاً من استطلاع صفحة الحالة.
$upstream_addr إلى سجل الوصول. يُسجّل خادم backend الذي عالج كل طلب، مما يجعل التحقق من عمل التوزيع أمراً سهلاً وربط الأخطاء بـ upstream محدد خلال حوادث الإنتاج. أضف $upstream_response_time إلى جانبه للكشف عن الخوادم ذات الكمون الشاذ.