عند تطوير تطبيقات الشبكة المحملة للغاية ، هناك حاجة إلى موازنة التحميل.
أداة موازنة L7 الشائعة هي Nginx. يسمح لك بتخزين الإجابات مؤقتًا واختيار استراتيجيات مختلفة وحتى كتابة نصوص LUA.
على الرغم من كل سحر Nginx ، إذا:
- لا حاجة للعمل مع HTTP (s).
- تحتاج إلى ضغط الحد الأقصى خارج الشبكة.
- ليست هناك حاجة لتخزين أي شيء مؤقتًا - فالموازن يحتوي على خوادم API نظيفة مزودة بديناميات.
قد يطرح السؤال التالي: لماذا تحتاج إلى Nginx؟ لماذا تنفق الموارد على موازنة L7 ، أليس من السهل إعادة توجيه حزمة SYN؟ (L4 التوجيه المباشر).
توازن الطبقة 4 أو كيفية التوازن في العصور القديمة
كانت أداة إعادة توجيه الحزم الشائعة هي IPVS. أجرى مهام الموازنة من خلال النفق والتوجيه المباشر.
في الحالة الأولى ، تم إنشاء قناة TCP لكل اتصال وذهبت الحزمة من المستخدم إلى الموازن ، ثم إلى العميل ، ثم بالترتيب العكسي.

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

في حالة التوجيه المباشر ، تذهب حزم الإرجاع مباشرة إلى المستخدم ، متجاوزة الموازن. من الواضح ، يتم حفظ كل من موارد الموازن والشبكة. من خلال توفير موارد الشبكة ، فإنها لا توفر الكثير من حركة المرور ، لأن الممارسة المعتادة هي توصيل الخوادم بشبكة منفصلة وليس لحساب حركة المرور ، ولكن الحقيقة هي أن النقل حتى من خلال الموازن يمثل خسارة بالميلي ثانية.
هذه الطريقة تفرض قيودًا معينة:
- يجب أن يسمح مركز البيانات الذي توجد به البنية التحتية بانتحال العناوين المحلية. في الرسم البياني أعلاه ، يجب على كل عميل إرسال الحزم مرة أخرى نيابة عن IP 10.10.0.1 ، والتي تم تعيينها للموازن.
- الموازن لا يعرف شيئًا عن حالة التوابع. وبالتالي ، فإن استراتيجيات Least Conn و Least Time ليست ممكنة. في إحدى المقالات التالية سأحاول تنفيذها وإظهار النتيجة.
هنا يأتي NFTables
قبل بضع سنوات ، بدأ Linux الترويج بنشاط لـ NFTables كبديل عن IPTables و ArpTables و EBTables والجميع [az] {1،} الجداول. في الوقت الذي كنا فيه في Adram بحاجة إلى الضغط على كل ميلي ثانية من الإجابة من الشبكة ، قررت سحب المدقق والبحث - أو ربما تعلمت ipTables القيام بإعادة توجيه iphash ويمكنك تسريعها لتحقيق التوازن. ثم تعثرت على nftables ، والتي يمكن وليس فقط ذلك ، ولكن لا يزال iptables لا يستطيع حتى القيام بذلك.
بعد عدة أيام من التجربة ، تمكنت أخيرًا من الحصول على التوجيه المباشر وتوجيه القنوات من خلال NFTables في مختبر الاختبار وقياسها أيضًا مقارنة بـ nginx.
لذلك ، مختبر الاختبار. لدينا 5 سيارات:
- nft-router - جهاز توجيه يقوم بمهمة توصيل العميل والشبكة الفرعية AppServer. يحتوي على بطاقتي شبكة: 192.168.56.254 - ينظر إلى شبكة خادم التطبيق ، 192.168.97.254 - ينظر إلى العملاء. يتم تمكين Ip_forward ويتم تسجيل جميع المسارات.
- nft-client: العميل الذي سيتم منه تعقب ab ، ip 192.168.97.2
- موازنة nft: الموازن. لديها اثنين من عناوين IP: 192.168.56.4 ، والتي يصل إليها العملاء و 192.168.13.1 ، من الشبكة الفرعية العميل.
- nft-minion-a و nft-minion-b: minions ipy: 192.168.56.2 و 192.168.56.3 و 192.168.13.2 و 192.168.13.3 (حاولت استخدام نفس الشبكة ومختلفة لتحقيق التوازن). في الاختبارات ، توقفت عن حقيقة أن التوابع لها أنواع "خارجية" - في الشبكة الفرعية 192.168.56.0/24
جميع واجهات MTU 1500.
التوجيه المباشر
إعدادات NFTables على الموازن:
table ip raw { chain input { type filter hook prerouting priority -300; policy accept; tcp dport http ip daddr set jhash tcp sport mod 2 map { 0: 192.168.56.2, 1: 192.168.56.3 } } }
يتم إنشاء سلسلة خام ، على الخطاف ، مع أولوية -300.
إذا وصلت حزمة تحتوي على عنوان وجهة http ، ثم اعتمادًا على المنفذ المصدر (الذي تم إجراؤه للاختبار من جهاز واحد ، فأنت بحاجة فعليًا إلى ip saddr) ، إما 56.2 أو 56.3 يتم تحديدهما وتعيينهما كعنوان الوجهة في الحزمة ، ثم يتم إرسالهما على طول المسارات. بمعنى تقريبي ، بالنسبة للمنافذ حتى 56.2 ، بالنسبة للمنافذ الفردية ، على التوالي ، 56.3 (في الواقع ، لا ، لأنه من أجل التجزئة / الفردية ، لكن من السهل فهم ذلك تمامًا). بعد ضبط عنوان IP المستهدف ، تعود الحزمة إلى الشبكة. لا يحدث أي NAT ، تأتي الحزمة إلى العميل مع IP المصدر للعميل ، وليس الموازن ، وهو أمر مهم للتوجيه المباشر.
إعدادات العميل NFT:
table ip raw { chain output { type filter hook output priority -300; policy accept; tcp sport http ip saddr set 192.168.56.4 } }
يتم إنشاء ربط الإخراج الخام مع أولوية -300 (الأولوية مهمة للغاية هنا ، في المستويات العليا لن يعمل mengling الضروري لحزم الرد).
يتم توقيع كل حركة المرور الصادرة من منفذ http بواسطة 56.4 (ip balancer) وإرسالها مباشرة إلى العميل ، متجاوزة الموازن.
للتحقق مما إذا كان كل شيء سوف يعمل بشكل صحيح ، أحضرت العميل إلى شبكة أخرى والسماح لها من خلال جهاز التوجيه.
لقد قمت أيضًا بتعطيل arp_filter و rp_filter (بحيث عملت عملية الغش) وتمكين ip_forward على كل من الموازن وعلى جهاز التوجيه.
بالنسبة للمقاعد ، في حالة NFT ، يتم استخدام Nginx + php7.2-FPM من خلال مقبس يونيكس في كل عميل. لم يكن هناك شيء على الموازن.
في حالة Nginx ، استخدمنا: nginx على الموازن و php7.2-FPM عبر TCP على التوابع. نتيجةً لذلك ، لم أوازن بين خادم الويب وراء الموازن ، ولكن على الفور FPM (الذي سيكون أكثر صدقًا مع nginx ، وأكثر اتساقًا مع الحياة الحقيقية).
بالنسبة لـ NFT ، تم استخدام استراتيجية التجزئة فقط (
nft dr في الجدول) ، لـ nginx: hash (
ngx eq ) و conn الأقل (
ngx lc )
تم إجراء العديد من الاختبارات.
- نص سريع صغير (صغير) .
<?php system('hostname');
- البرنامج النصي مع تأخير عشوائي (راند) .
<?php usleep(mt_rand(100000,200000)); echo "ok";
- برنامج نصي مع إرسال كمية كبيرة من البيانات (الحجم) .
<?php $size=$_GET['size']; $file='/tmp/'.$size; if (!file_exists($file)) { $dummy=""; exec ("dd if=/dev/urandom of=$file bs=$size count=1 2>&1",$dummy); } fpassthru (fopen($file,'rb'));
تم استخدام الأحجام التالية:
512.1440.1460.1480.1500.2048.65535.655350 bytes.
قبل الاختبارات ، استعدت ملفات احصائيات على كل عميل.
اختبار أب ثلاث مرات في كل اختبار:
في البداية ، خططت لتقديم وقت الاختبار ، بالميلي ثانية والباقي ، كنت قد توقفت عند RPS - فهي تمثيلية وترتبط بمؤشرات الوقت.
حصلت على النتائج التالية:
اختبار الحجم - الأعمدة - حجم البيانات المقدمة.

كما ترون ، يفوز التوجيه المباشر nft بهامش كبير.
كنت أعول على عدد قليل من النتائج الأخرى المتعلقة بحجم إطار إيثرنت ، ولكن لم يتم العثور على أي ارتباط. ربما لا يناسب 512 جسمًا 1500 وحدة من وحدات النقل ، على الرغم من أنني أشك في أن الاختبار الصغير سيكون مؤشراً.
لقد لاحظت أنه على وحدات التخزين الكبيرة (650 كيلو بايت) nginx يقلل من الفصل. ربما هذا له علاقة مع المخازن المؤقتة وحجم TCP Windows.
نتيجة اختبار راند. يوضح كيفية تعامل conn الأقل في ظروف سرعة تنفيذ النص المختلفة على التوابع المختلفة.

من المثير للدهشة أن تجزئة nginx عملت بشكل أسرع من كون الأقل ، وفقط في التمريرة النهائية لم يتقدم كون إلى الأمام قليلاً ، وهو ما لا يدعي أنه مهم.
تختلف أرقام التمريرات اختلافًا كبيرًا نظرًا لحقيقة أن 100 مؤشر ترابط تترك في وقت واحد ، وأن FPM-ok من البداية تبدأ بحوالي 10. وبمرور الوقت الثالث ، كان لديهم وقت للتعود عليه - مما يدل على قابلية تطبيق الاستراتيجيات للرشقات.
NFT من المتوقع أن يخسر هذا الاختبار. يحسن Nginx التفاعل مع FPMs بشكل جيد في مثل هذه الحالات.
اختبار صغير

فوز nft بشكل هامشي على RPS ، الأقل conn مرة أخرى غريب.
بالمناسبة ، في هذا الاختبار ، يتم إصدار 400-500RPS ، على الرغم من أنه في الاختبار الذي أرسل 512 بايت كان 1500 ، يبدو أن النظام يأكل هذا الف.
الاستنتاجات
كان أداء NFT جيدًا في حالة تحسين الأحمال المنتظمة: عندما يتم إعطاء الكثير من البيانات ، ويتم تحديد وقت تشغيل التطبيق وتكون موارد المجموعة كافية لمعالجة الدفق الوارد دون الخوض في tailspin.
في الحالة التي يكون فيها التحميل لكل طلب فوضويًا ويستحيل موازنة تحميل الخادم بالتساوي مع الباقي البدائي من قسم التجزئة ، ستفقد NFT.