ما هو نوع الحمل على الخوادم التي تنشئ آليات الشبكة؟

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





معالجة حزم الشبكة على Linux


يعالج Linux عددًا كبيرًا من الحزم في سياق أي عملية ينفذها المعالج في وقت معالجة IRQ المقابل. سيعين محرك محاسبة النظام دورات المعالج المستخدمة لهذا في أي عملية يتم تنفيذها حاليًا. سيتم تنفيذ ذلك حتى إذا كانت هذه العملية لا علاقة لها بمعالجة حزم الشبكة. على سبيل المثال ، topقد يشير الفريق إلى أنه يبدو أن العملية تستخدم أكثر من 99٪ من موارد المعالج ، ولكن في الواقع سيتم إنفاق 60٪ من وقت المعالج على معالجة الحزم. وهذا يعني أن العملية نفسها ، حل مشاكلها الخاصة ، تستخدم 40٪ فقط من موارد وحدة المعالجة المركزية.

معالج الواردnet_rx_actionعادة ما يؤدي بسرعة كبيرة. على سبيل المثال ، في أقل من 25 μs. (تم الحصول على هذه البيانات من القياسات باستخدام eBPF. إذا كنت مهتمًا بالتفاصيل ، فابحث هنا net_rx_action .) يمكن للمعالج معالجة حتى 64 رزمة لكل مثيل NAPI (NIC أو RPS) قبل تأجيل المهمة إلى دورة SoftIRQ أخرى. واحدًا تلو الآخر ، دون انقطاع ، يمكن متابعة ما يصل إلى 10 دورات SoftIRQ ، والتي تستغرق حوالي 2 مللي ثانية (يمكنك معرفة المزيد عن هذا عن طريق القراءة عن __do_softirq). إذا كان متجه SoftIRQ ، بعد مرور الحد الأقصى لعدد الدورات ، أو مرور الوقت ، لا يزال لديه مشاكل لم يتم حلها ، فإن حل هذه المشاكل يتأخر للتنفيذ في سلسلة المحادثاتksoftirqdوحدة معالجة مركزية محددة. عندما يحدث ذلك ، يتبين أن النظام يكون أكثر شفافية قليلاً بمعنى الحصول على معلومات حول حمل المعالج الذي تم إنشاؤه بواسطة عمليات الشبكة (على الرغم من أن هذا التحليل يتم على افتراض أنه يتم فحص SoftIRQ ، والذي يتعلق بمعالجة الحزم ، وليس بشيء آخر) .

إحدى الطرق للحصول على المؤشرات المذكورة أعلاه هي استخدام perf:

sudo perf record -a \
        -e irq:irq_handler_entry,irq:irq_handler_exit
        -e irq:softirq_entry --filter="vec == 3" \
        -e irq:softirq_exit --filter="vec == 3"  \
        -e napi:napi_poll \
        -- sleep 1

sudo perf script

ها هي النتيجة:

swapper     0 [005] 176146.491879: irq:irq_handler_entry: irq=152 name=mlx5_comp2@pci:0000:d8:00.0
swapper     0 [005] 176146.491880:  irq:irq_handler_exit: irq=152 ret=handled
swapper     0 [005] 176146.491880:     irq:softirq_entry: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491942:        napi:napi_poll: napi poll on napi struct 0xffff9d3d53863e88 for device eth0 work 64 budget 64
swapper     0 [005] 176146.491943:      irq:softirq_exit: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491943:     irq:softirq_entry: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491971:        napi:napi_poll: napi poll on napi struct 0xffff9d3d53863e88 for device eth0 work 27 budget 64
swapper     0 [005] 176146.491971:      irq:softirq_exit: vec=3 [action=NET_RX]
swapper     0 [005] 176146.492200: irq:irq_handler_entry: irq=152 name=mlx5_comp2@pci:0000:d8:00.0

في هذه الحالة ، يكون المعالج خاملاً (ومن ثم ظهور إدخالات swapperللعملية) ، يتم استدعاء IRQ لقائمة انتظار Rx على وحدة المعالجة المركزية 5 ، وتسمى معالجة SoftIRQ مرتين ، ويتم معالجة 64 حزمة أولاً ، ثم 27. يتم استدعاء IRQ التالي بعد 229 μs ويبدأ الدورة مرة أخرى.

تم الحصول على هذه البيانات على نظام خامل. ولكن على المعالج ، يمكن تنفيذ أي مهمة. في هذه الحالة ، يحدث تسلسل الأحداث أعلاه ، مما يؤدي إلى مقاطعة هذه المهمة وتنفيذ مهام IRQ / SoftIRQ. في الوقت نفسه ، تنسب محاسبة النظام إلى العملية المتقطعة الحمل الذي أنشأه المعالج. ونتيجة لذلك ، عادةً ما تكون مهام معالجة حزم الشبكة مخفية عن أدوات مراقبة حمل المعالج التقليدية. يتم تنفيذها في سياق عملية مختارة عشوائياً ، في سياق "عملية الضحية". هذا يقودنا إلى بعض الأسئلة. كيفية تقدير الوقت الذي توقفت فيه العملية لمعالجة الحزم؟ كيفية مقارنة حلين مختلفين للشبكة من أجل فهم أي منهما له تأثير أقل على مختلف المهام التي تم حلها على جهاز الكمبيوتر؟

عند استخدام آليات RSS و RPS و RFS ، يتم عادةً توزيع الحزم بين نوى المعالج. لذلك ، يرتبط تسلسل معالجة الحزم أعلاه بكل وحدة معالجة مركزية محددة. مع زيادة معدل وصول الحزمة (أعتقد أنه يمكننا التحدث عن سرعات 100،000 حزمة في الثانية وأعلى) ، يجب على كل وحدة معالجة مركزية معالجة آلاف أو عشرات الآلاف من الحزم في الثانية. ستؤثر معالجة العديد من الحزم حتمًا على المهام الأخرى التي يتم إجراؤها على الخادم.

فكر في طريقة واحدة لتقييم هذا التأثير.

تعطيل معالجة الحزم الموزعة


للبدء ، دعنا نوقف المعالجة الموزعة للحزم عن طريق تعطيل RPS وإعداد قواعد التحكم في التدفق التي تهدف إلى تنظيم معالجة جميع الحزم المتعلقة بعنوان MAC معين على وحدة المعالجة المركزية الوحيدة المعروفة لنا. يحتوي نظامي على 2 بطاقة NIC مجمعة في تكوين 802.3ad. يتم تعيين مهام الشبكة إلى جهاز ظاهري واحد يعمل على جهاز الكمبيوتر.

تم تعطيل RPS على محولات الشبكة كما يلي:

for d in eth0 eth1; do
    find /sys/class/net/${d}/queues -name rps_cpus |
    while read f; do
            echo 0 | sudo tee ${f}
    done
done

بعد ذلك ، قمنا بإعداد قواعد التحكم في التدفق لضمان دخول الحزم إلى الجهاز الظاهري التجريبي باستخدام وحدة معالجة مركزية واحدة:

DMAC=12:34:de:ad:ca:fe
sudo ethtool -N eth0 flow-type ether dst ${DMAC} action 2
sudo ethtool -N eth1 flow-type ether dst ${DMAC} action 2

يسمح لنا تعطيل RPS واستخدام قواعد التحكم في التدفق بالتأكد من معالجة جميع الحزم الموجهة لجهازنا الافتراضي على نفس وحدة المعالجة المركزية. للتأكد من إرسال الحزم إلى قائمة الانتظار التي يجب إرسالها إليها ، يمكنك استخدام أمر مثل ethq . ثم يمكنك معرفة وحدة المعالجة المركزية التي تنتمي إليها قائمة الانتظار هذه /proc/interrupts. في حالتي ، تتم معالجة بدوره 2 عن طريق وحدة المعالجة المركزية 5.

أمر سرعة Openssl


يمكنني استخدام الأدوات المساعدة perfأو تحليل أوقات تشغيل SoftIRQ المسؤولة عن معالجة حركة المرور الواردة bpf، ولكن هذا النهج معقد للغاية. بالإضافة إلى ذلك ، فإن عملية المراقبة نفسها تؤثر بالتأكيد على النتائج. إن الحل الأبسط والأكثر قابلية للفهم هو تحديد الحمل الذي تم إنشاؤه بواسطة عمليات الشبكة على النظام باستخدام بعض المهام ، التي تخلق حملًا معروفًا على النظام. على سبيل المثال ، هذا أمر openssl speedيستخدم لاختبار أداء OpenSSL. سيسمح لك هذا بمعرفة مقدار موارد المعالج التي يحصل عليها البرنامج في الواقع ، ومقارنته بكمية الموارد التي من المفترض أن يتلقىها (سيساعد هذا في معرفة مقدار الموارد التي يتم إنفاقها على مهام الشبكة).

الفريق ما openssl speedيقرب من 100٪ فريق مساحة المستخدم. إذا قمت بربطه بوحدة معالجة مركزية معينة ، فإنه أثناء تنفيذ الاختبارات ، يستخدم جميع موارده المتاحة. يعمل الفريق عن طريق ضبط المؤقت على الفاصل الزمني المحدد (هنا ، على سبيل المثال ، لتسهيل العمليات الحسابية ، يستغرق 10 ثوانٍ) ، وتشغيل الاختبار ، وبعد ذلك ، عند تشغيل المؤقت ، يستخدمه times()لمعرفة مقدار وقت المعالج الذي حصل عليه البرنامج بالفعل. من وجهة نظر syscallتبدو كما يلي:

alarm(10)                               = 0
times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726601344
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
rt_sigaction(SIGALRM, ...) = 0
rt_sigreturn({mask=[]}) = 2782545353
times({tms_utime=1000, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726602344

أي ، اتضح أن alarm()مكالمات النظام قليلة جدًا تم إجراؤها بين الاتصال والتحقق من النتائج. إذا لم تتم مقاطعة البرنامج ، أو تمت مقاطعته نادرًا جدًا ، فإن الوقت tms_utimeسيتزامن مع وقت الاختبار (في هذه الحالة ، 10 ثوانٍ).

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

alarm(10)                               = 0
times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726617896
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
rt_sigaction(SIGALRM, ...) = 0
rt_sigreturn({mask=[]}) = 4079301579
times({tms_utime=178, tms_stime=571, tms_cutime=0, tms_cstime=0}) = 1726618896

هنا يمكنك أن ترى أنه كان من opensslالممكن العمل على المعالج لمدة 7.49 ثانية (178 + 571 في وحدات القياس المقابلة لـ 0.01 ثانية). ولكن في نفس الوقت 5.71 ثانية. يتم تمثيل هذا الفاصل الزمني بوقت النظام. نظرًا لأنه opensslليس مشغولًا بأي عمل في مساحة النواة ، فهذا يعني أن 5.71 ثانية. - هذا نتيجة بعض الحمل الإضافي على النظام. هذا هو الوقت الذي "سُرقت فيه" العملية من أجل تلبية احتياجات النظام.

استخدام الأمر opensl speed للكشف عن حمل النظام الناتج عن آليات الشبكة


الآن بعد أن اكتشفنا كيفية عمل الفريق openssl speed، سنلقي نظرة على النتائج التي ينتجها على خادم غير نشط عمليًا:

$ taskset -c 5 openssl speed -seconds 10 aes-256-cbc >/dev/null
Doing aes-256 cbc for 10s on 16 size blocks: 66675623 aes-256 cbc's in 9.99s
Doing aes-256 cbc for 10s on 64 size blocks: 18096647 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 256 size blocks: 4607752 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 1024 size blocks: 1162429 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 8192 size blocks: 145251 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 16384 size blocks: 72831 aes-256 cbc's in 10.00s

كما ترى ، يتم إعلامنا أن البرنامج ينفق من 9.99 إلى 10 ثوانٍ لمعالجة الكتل ذات الأحجام المختلفة. هذا يؤكد أن آليات النظام لا تستغرق وقت المعالج من البرنامج. الآن ، باستخدام netperf، سنقوم بتحميل الخادم عن طريق معالجة الحزم القادمة من مصدرين. شغّل الاختبار مرة أخرى:

$ taskset -c 5 openssl speed -seconds 10 aes-256-cbc >/dev/null
Doing aes-256 cbc for 10s on 16 size blocks: 12061658 aes-256 cbc's in 1.96s
Doing aes-256 cbc for 10s on 64 size blocks: 3457491 aes-256 cbc's in 2.10s
Doing aes-256 cbc for 10s on 256 size blocks: 893939 aes-256 cbc's in 2.01s
Doing aes-256 cbc for 10s on 1024 size blocks: 201756 aes-256 cbc's in 1.86s
Doing aes-256 cbc for 10s on 8192 size blocks: 25117 aes-256 cbc's in 1.78s
Doing aes-256 cbc for 10s on 16384 size blocks: 13859 aes-256 cbc's in 1.89s

النتائج مختلفة تمامًا عن تلك التي تم الحصول عليها على خادم خامل. من المتوقع أن يتم تنفيذ كل اختبار خلال 10 ثوانٍ ، لكن times()التقارير تشير إلى أن وقت التنفيذ الفعلي يتراوح من 1.78 إلى 2.1 ثانية. وهذا يعني أن الوقت المتبقي ، الذي يتراوح من 7.9 إلى 8.22 ثانية ، تم إنفاقه على معالجة الحزم ، إما في سياق العملية opensslأو في ksoftirqd.

دعنا نلقي نظرة على ما سيعطيه الفريق topعند تحليل الإطلاق الذي اكتمل لتوه openssl speed.

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND              P 
 8180 libvirt+  20   0 33.269g 1.649g 1.565g S 279.9  0.9  18:57.81 qemu-system-x86     75
 8374 root      20   0       0      0      0 R  99.4  0.0   2:57.97 vhost-8180          89
 1684 dahern    20   0   17112   4400   3892 R  73.6  0.0   0:09.91 openssl              5    
   38 root      20   0       0      0      0 R  26.2  0.0   0:31.86 ksoftirqd/5          5

هنا قد تعتقد أنها opensslتستخدم حوالي 73٪ من موارد وحدة المعالجة المركزية 5 ، ksoftirqdويتم الحصول على الموارد المتبقية. ولكن في الواقع ، في السياق openssl، يتم تنفيذ هذا العدد الكبير من الحزم بحيث يستغرق البرنامج نفسه 18-21 ٪ فقط من وقت المعالج لحل مشاكله.

إذا قمت بتقليل حمل الشبكة إلى تيار واحد ، فإنك تشعر بأن openssl99٪ من موارد النظام يتم استهلاكها.

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND              P
 8180 libvirt+  20   0 33.269g 1.722g 1.637g S 325.1  0.9 166:38.12 qemu-system-x86     29
44218 dahern    20   0   17112   4488   3996 R  99.2  0.0   0:28.55 openssl              5
 8374 root      20   0       0      0      0 R  64.7  0.0  60:40.50 vhost-8180          55
   38 root      20   0       0      0      0 S   1.0  0.0   4:51.98 ksoftirqd/5          5

ولكن في الواقع اتضح أن البرنامج الذي يتم تشغيله في مساحة المستخدم يحصل على ، من الثواني العشر المتوقعة ، حوالي 4 ثوان فقط:

Doing aes-256 cbc for 10s on 16 size blocks: 26596388 aes-256 cbc's in 4.01s
Doing aes-256 cbc for 10s on 64 size blocks: 7137481 aes-256 cbc's in 4.14s
Doing aes-256 cbc for 10s on 256 size blocks: 1844565 aes-256 cbc's in 4.31s
Doing aes-256 cbc for 10s on 1024 size blocks: 472687 aes-256 cbc's in 4.28s
Doing aes-256 cbc for 10s on 8192 size blocks: 59001 aes-256 cbc's in 4.46s
Doing aes-256 cbc for 10s on 16384 size blocks: 28569 aes-256 cbc's in 4.16s

تشير أدوات مراقبة العمليات التقليدية إلى أن البرنامج يستخدم جميع موارد المعالج تقريبًا ، ولكن في الواقع اتضح أن 55-80٪ من موارد وحدة المعالجة المركزية يتم إنفاقها على معالجة حزم الشبكة. يبدو إنتاجية النظام في نفس الوقت رائعًا (أكثر من 22 جيجابت / ثانية لكل خط 25 جيجابت / ثانية) ، ولكن هذا له تأثير هائل على العمليات قيد التشغيل في هذا النظام.

ملخص


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

هل تفكر في تحليل خوادمك والتأثير على أدائها الفعلي للحمل المرتبط بعمليات الشبكة؟


All Articles