أنا أعمق تحت الأرض ، أو ما يجب أن تعرفه ، تحسين تطبيق الشبكة

تحية الأصدقاء!

في المادتين السابقتين ( الأولى والثانية ) ، تراجعنا في تعقيد الاختيار بين التقنيات وبحثنا عن الإعدادات المثلى لحلنا في Ostrovok.ru . ما هو الموضوع الذي سنطرحه اليوم؟

يجب أن تعمل كل خدمة على بعض الخوادم ، وتتواصل مع الأجهزة من خلال أدوات نظام التشغيل. هناك عدد كبير من هذه الأدوات ، وكذلك الإعدادات الخاصة بها. في معظم الحالات ، ستكون إعداداتها الافتراضية أكثر من كافية. في هذه المقالة ، أود أن أتحدث عن تلك الحالات عندما كانت الإعدادات القياسية لا تزال غير كافية ، واضطررت إلى التعرف على نظام التشغيل بشكل أقرب قليلاً - في حالتنا مع Linux .



نحن نستخدم حبات بحكمة


في مقال سابق ، تحدثت عن خيار cpu-map في Haproxy . مع ذلك ، نربط عمليات Haproxy بخيوط أساسية واحدة على خادم ثنائي المعالج. لقد قدمنا ​​النواة الثانية للتعامل مع بطاقة الشبكة.

يوجد أدناه شاشة يمكنك من خلالها رؤية فصل مماثل. على اليسار ، يشغل Haproxy النواة في user space ، وعلى اليمين ، عن طريق معالجة المقاطعات في kernel space .



يتم ربط المقاطعات ببطاقة الشبكة تلقائيًا باستخدام هذا
نص باش:
 #! /bin/bash interface=${1} if [ -z "${interface}" ];then echo "no interface specified" echo "usage: ${0} eth1" exit 1 fi nproc=$(grep 'physical id' /proc/cpuinfo|sort -u|wc -l) ncpu=$(grep -c 'processor' /proc/cpuinfo) cpu_per_proc=$[ncpu / nproc] queue_threads=$[cpu_per_proc / 2] binary_map="" cpumap="" for(( i=0; i < ncpu; i++ ));do cpumap=${cpumap}1 b+='{0..1}' done binary_map=($(eval echo ${b})) ###         ###    ,      . ethtool -L ${interface} combined ${queue_threads} || true count=${ncpu} while read irq queue;do let "cpu_num=$[count-1]" let "cpu_index=$[2**cpu_num]" printf "setting ${queue} to %d (%d)\n" $((2#${binary_map[${cpu_index}]})) ${cpu_num} printf "%x\n" "$((2#${binary_map[${cpu_index}]}))" > /proc/irq/${irq}/smp_affinity [ ${interface} != ${queue} ] && count=$[count-1] [ $[ncpu - count] -gt ${queue_threads} ] && count=${ncpu} done < <(awk "/${interface}/ {if(NR > 1){ sub(\":\", \"\", \$1); print \$1,\$(NF)} }" /proc/interrupts) exit 0 


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

في Haproxy ، قمنا بربط العمليات بالنواة ، بدءًا من النواة الأولى. البرنامج النصي نفسه يربط المقاطعات ، بدءاً من الأخير. وبالتالي ، يمكننا تقسيم معالجات الخوادم إلى معسكرين.

للحصول على نظرة أعمق إلى الانقطاعات والشبكات ، أوصي بشدة قراءة هذه المقالة .

نكشف عن قدرات أجهزة الشبكة


يحدث أن العديد من الإطارات يمكن أن تطير عبر الشبكة في لحظة واحدة ، وقد لا تكون قائمة انتظار البطاقة جاهزة لمثل هذا التدفق من الضيوف ، حتى لو كانت لديها الفرصة للقيام بذلك.

دعونا نتحدث عن المخزن المؤقت لبطاقة الشبكة. في أغلب الأحيان ، لا تستخدم القيم الافتراضية المخزن المؤقت المتوفر بأكمله. يمكنك عرض الإعدادات الحالية باستخدام الأداة المساعدة ethtool القوية.

مثال على استخدام الأوامر:

 > ethtool -g eno1 Ring parameters for eno1: Pre-set maximums: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096 Current hardware settings: RX: 256 RX Mini: 0 RX Jumbo: 0 TX: 256 

الآن لنأخذ كل شيء من الحياة:

 > ethtool -G eno1 rx 4096 tx 4096 > ethtool -g eno1 Ring parameters for eno1: Pre-set maximums: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096 Current hardware settings: RX: 4096 RX Mini: 0 RX Jumbo: 0 TX: 4096 

الآن يمكنك التأكد من أن البطاقة ليست مقيدة وتعمل بأقصى قدر من إمكاناتها.

الحد الأدنى من إعدادات sysctl لتحقيق أقصى فائدة


Sysctl لديها مجموعة كبيرة ومتنوعة من الخيارات في جميع الألوان والأحجام التي يمكنك تخيلها. وكقاعدة عامة ، تغطي المقالات على الإنترنت ، والتي تتناول مسألة التحسين ، جزءًا مثيرًا للإعجاب من هذه المعايير. سوف أفكر فقط في تلك التي كانت مفيدة حقا للتغيير في حالتنا.

net.core.netdev_max_backlog - قائمة الانتظار التي تحصل عليها الإطارات من بطاقة الشبكة ، والتي تتم معالجتها بعد ذلك بواسطة kernel. مع واجهات سريعة وكميات كبيرة من حركة المرور ، يمكن أن تملأ بسرعة. الافتراضي : 1000.
يمكننا ملاحظة الزيادة في قائمة الانتظار هذه من خلال النظر إلى العمود الثاني في ملف / proc / net / softnet_stat.
 awk '{print $2}' /proc/net/softnet_stat 

يصف الملف نفسه بنية netif_rx_stats لكل سطر لكل وحدة المعالجة المركزية في النظام.
على وجه التحديد ، يصف العمود الثاني عدد الحزم في الحالة المسقطة. إذا كانت القيمة في العمود الثاني تنمو بمرور الوقت ، فقد يكون من المفيد زيادة قيمة net.core.netdev_max_backlog أو وضع وحدة المعالجة المركزية بشكل أسرع.

net.core.rmem_default / net.core.rmem_max && net.core.wmem_default / net.core.wmem_max - تشير هذه المعلمات إلى القيمة الافتراضية / الحد الأقصى لقيمة المخازن المؤقتة للقراءة والكتابة. يمكن تغيير القيمة الافتراضية على مستوى التطبيق في وقت إنشاء المقبس (بالمناسبة ، لدى Haproxy معلمة تقوم بذلك). كانت لدينا حالات عندما ألقى النواة حزمًا أكثر مما تمكنت هابروكسي من إدارته ، ثم بدأت المشاكل. لذلك ، الشيء المهم.

net.ipv4.tcp_max_syn_backlog - مسؤول عن الحد من الاتصالات الجديدة التي لم يتم تأسيسها بعد والتي تم استلام حزمة SYN لها. إذا كان هناك دفق كبير من الاتصالات الجديدة (على سبيل المثال ، الكثير من طلبات HTTP من Connection: close ) ، فمن المنطقي رفع هذه القيمة حتى لا تضيع الوقت في إرسال الحزم المعاد توجيهها.

net.core.somaxconn - هنا نتحدث عن الاتصالات القائمة ، ولكن لم تتم معالجتها بعد بواسطة التطبيق. إذا كان الخادم مترابطًا واحدًا ، وتم تقديم طلبين ، فستتم معالجة الطلب الأول من خلال وظيفة accept() ، وسيتم تعليق الطلب الثاني في الأعمال backlog ، التي يكون حجمها مسؤولاً عن هذه المعلمة.

ربما يكون nf_conntrack_max هو الأكثر شهرة بين جميع المعلمات. أعتقد أن كل من تعامل مع iptables يعرف ذلك تقريبًا. من الناحية المثالية ، بالطبع ، إذا لم تكن بحاجة إلى استخدام iptables المتنكر ، فيمكنك إلغاء تحميل وحدة conntrack وعدم التفكير في الأمر. في حالتي ، يتم استخدام Docker ، لذلك لن تقوم بتحميل أي شيء خاص.

الرصد واضح وليس جدا


لكي لا تبحث عمياء عن سبب "تباطؤ وكيلك" ، سيكون من المفيد إعداد زوجين من الرسوم البيانية ووضعها على المشغلات.

nf_conntrack_count هو المقياس الأكثر وضوحًا. على ذلك ، يمكنك مراقبة عدد الاتصالات الموجودة الآن في جدول conntrack . عندما يفيض الجدول ، سيتم إغلاق مسار الاتصالات الجديدة.

القيمة الحالية يمكن العثور عليها هنا:

 cat /proc/sys/net/netfilter/nf_conntrack_count 



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



في بلدنا ، تشير الزيادة في القيم غالبًا إلى وجود مشكلة مع أحد الموردين ، على الرغم من وجود مشكلات في أداء الخوادم والشبكة.

مثال للتحقق:

 netstat -s|grep 'segments retransmited' 

Socket Recv-Q - تذكر ، تحدثنا عن اللحظات التي قد لا يكون لدى التطبيق فيها ما يكفي من الوقت لمعالجة الطلبات ، ومن ثم سوف ينمو socket backlog ؟ يوضح نمو هذا المؤشر وجود خطأ في التطبيق ولا يمكن التعامل معه.

رأيت الجبال في الرسوم البيانية مع هذا المقياس ، عندما كانت المعلمة maxconn في Haproxy لها قيمة افتراضية (2000) ، وببساطة لم تقبل الاتصالات الجديدة.

ومرة أخرى مثال:

 ss -lntp|awk '/LISTEN/ {print $2}' 



لن يكون من الضروري وجود رسم بياني مع توزيع تفصيلي حسب حالة اتصالات TCP:



وعلى حدة تقديم time-wait/established ، ل تختلف قيمهم ، كقاعدة عامة ، عن البقية:



بالإضافة إلى هذه المقاييس ، هناك العديد من المعايير الأخرى ، ولكن أكثر وضوحًا - على سبيل المثال ، الحمل على واجهة الشبكة أو وحدة المعالجة المركزية. يعتمد اختيارهم بالفعل أكثر على تفاصيل عبء العمل الخاص بك.

بدلا من الاستنتاج


بشكل عام ، هذا كل شيء - حاولت وصف النقاط الرئيسية التي كان يجب علي مواجهتها عند إعداد http الوكيل العكسي. يبدو أن المهمة ليست صعبة ، ولكن مع زيادة في الحمل ، يزداد أيضًا عدد المزالق التي تنبثق دائمًا في الوقت الخطأ. آمل أن يساعدك هذا المقال في تجنب الصعوبات التي واجهتني.

كل السلام

Source: https://habr.com/ru/post/ar440782/


All Articles