لم تتضمن المنشورات السابقة على مدونة الشركة فريق وحدة تحكم واحد ، وقررنا اللحاق بالركب.
شركتنا لديها مقياس مصمم لمنع fakaps كبيرة على الاستضافة المشتركة. على كل خادم استضافة مشترك ، يوجد موقع اختبار على WordPress ، والذي يتم الوصول إليه بشكل دوري.

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

حدد المسؤولون على الفور السبب - نقص ذاكرة الوصول العشوائي. كان من السهل رؤية حالات OOM في السجلات عندما نفدت ذاكرة الخادم وقتل kernel nginx.
يقوم رئيس القسم ، أندري ، بتقسيم مهمة واحدة إلى عدة بواسطة يد المعالج ويوازيها مع المسؤولين المختلفين. سيقوم أحدهم بتحليل إعدادات Apache - ربما الإعدادات ليست مثالية ومع الكثير من حركة المرور تستخدم Apache كل الذاكرة؟ آخر يحلل استهلاك ذاكرة mysqld - فجأة هناك أي إعدادات قديمة من وقت استخدام الاستضافة المشتركة لنظام التشغيل Gentoo؟ يبحث الثالث في التغييرات الأخيرة على إعدادات nginx.
يعود المسؤولون واحداً تلو الآخر مع النتائج. تمكن كل منها من تقليل استهلاك الذاكرة في المساحة المخصصة له. في حالة nginx ، على سبيل المثال ، تم الكشف عن mod_security مضمنة ولكن غير مستخدمة. في هذه الأثناء ، OOM متكرر.
أخيرًا ، من الممكن ملاحظة أن استهلاك الذاكرة الأساسية (على وجه الخصوص ، SUnreclaim) كبير جدًا في بعض الخوادم. لا تظهر هذه المعلمة في إخراج ps ولا في htop ، لذلك لم نلاحظها على الفور! مثال على الخادم مع المطالبة الجهنمية:
root@vh28.timeweb.ru:~
24 غيغابايت من ذاكرة الوصول العشوائي تعطى للنواة ، والنواة تنفقها لأنه لا أحد يعرف ماذا!
المسؤول (دعنا ندعوه جبرائيل) يندفع إلى المعركة. يعيد تجميع النواة مع خيارات KMEMLEAK لاكتشاف التسرب.
خيارات لإعادة البناءلتمكين KMEMLEAK ، ما عليك سوى تحديد الخيارات المدرجة أدناه وتحميل النواة بالمعلمة kmemleak = on.
CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=10000
يكتب KMEMLEAK (في /sys/kernel/debug/kmemleak
) هذه السطور:
unreferenced object 0xffff88013a028228 (size 8): comm "apache2", pid 23254, jiffies 4346187846 (age 1436.284s) hex dump (first 8 bytes): 00 00 00 00 00 00 00 00 ........ backtrace: [<ffffffff818570c8>] kmemleak_alloc+0x28/0x50 [<ffffffff811d450a>] kmem_cache_alloc_trace+0xca/0x1d0 [<ffffffff8136dcc3>] apparmor_file_alloc_security+0x23/0x40 [<ffffffff81332d63>] security_file_alloc+0x33/0x50 [<ffffffff811f8013>] get_empty_filp+0x93/0x1c0 [<ffffffff811f815b>] alloc_file+0x1b/0xa0 [<ffffffff81728361>] sock_alloc_file+0x91/0x120 [<ffffffff8172b52e>] SyS_socket+0x7e/0xc0 [<ffffffff81003854>] do_syscall_64+0x54/0xc0 [<ffffffff818618ab>] return_from_SYSCALL_64+0x0/0x6a [<ffffffffffffffff>] 0xffffffffffffffff unreferenced object 0xffff880d67030280 (size 624): comm "hrrb", pid 23713, jiffies 4346190262 (age 1426.620s) hex dump (first 32 bytes): 01 00 00 00 03 00 ff ff 00 00 00 00 00 00 00 00 ................ 00 e7 1a 06 10 88 ff ff 00 81 76 6e 00 88 ff ff ..........vn.... backtrace: [<ffffffff818570c8>] kmemleak_alloc+0x28/0x50 [<ffffffff811d4337>] kmem_cache_alloc+0xc7/0x1d0 [<ffffffff8172a25d>] sock_alloc_inode+0x1d/0xc0 [<ffffffff8121082d>] alloc_inode+0x1d/0x90 [<ffffffff81212b01>] new_inode_pseudo+0x11/0x60 [<ffffffff8172952a>] sock_alloc+0x1a/0x80 [<ffffffff81729aef>] __sock_create+0x7f/0x220 [<ffffffff8172b502>] SyS_socket+0x52/0xc0 [<ffffffff81003854>] do_syscall_64+0x54/0xc0 [<ffffffff818618ab>] return_from_SYSCALL_64+0x0/0x6a [<ffffffffffffffff>] 0xffffffffffffffff
لم يكشف غابرييل عن كل أسراره لنا ولم يخبرنا كيف اكتشف من الأسطر أعلاه السبب الدقيق لتسرب الذاكرة. على الأرجح ، استخدم الأمر addr2line /usr/lib/debug/lib/modules/`uname -r`/vmlinux ffffffff81722361
للعثور على السطر بالضبط. أو فقط فتح net/socket.c
ونظرت فيه حتى أصبح الملف غير مريح.
تحولت المشكلة إلى تصحيح على net/socket.c
، والذي تمت إضافته إلى net/socket.c
منذ سنوات عديدة. الغرض منه هو منع العملاء من استخدام استدعاء النظام bind () ، هذه حماية بسيطة ضد الخادم الوكيل بدءًا من العملاء. حقق الرقعة غرضه ، لكنه لم يمسح الذاكرة بعده.
ربما كانت هناك برامج ضارة عصرية جديدة في PHP حاولت تشغيل خادم وكيل في حلقة - مما أدى إلى مئات الآلاف من المكالمات المربوطة () المحظورة وفقدان غيغابايت من ذاكرة الوصول العشوائي.
ثم كان الأمر بسيطًا - قام جبرائيل بإصلاح الرقعة وأعاد بناء النواة. تمت إضافة مراقبة لقيمة SUnreclaim على جميع الخوادم التي تعمل بنظام Linux. حذر المهندسون العملاء وأعادوا الاستضافة في النواة الجديدة.
اختفى OOM.
لكن مشكلة توفر المواقع ظلت قائمة
على جميع الخوادم ، توقف موقع الاختبار عن الاستجابة عدة مرات في اليوم.
هنا ، سيبدأ المؤلف بتمزيق الشعر على أجزاء مختلفة من الجسم. لكن غابرييل ظل هادئًا وشغل تسجيل حركة المرور إلى أجزاء من خوادم الاستضافة.
في تفريغ حركة المرور ، لوحظ أنه في معظم الأحيان يسقط الطلب إلى موقع الاختبار بعد الاستلام المفاجئ لحزمة TCP RST
. وبعبارة أخرى ، وصل الطلب إلى الخادم ، ولكن انتهى الاتصال بسبب nginx.
أكثر إثارة للاهتمام! تُظهر الأداة المساعدة التي أطلقها Gabriel أن برنامج nginx daemon لا يرسل هذه الحزمة. كيف يمكن ذلك ، لأن nginx فقط هو الذي يستمع على المنفذ 80؟
كان السبب مزيجًا من عدة عوامل:
- في إعدادات nginx ، يتم
reuseport
خيار reuseport
(بما في ذلك SO_REUSEPORT
مأخذ SO_REUSEPORT
) ، والذي يسمح للعمليات المختلفة بقبول الاتصالات على نفس العنوان والمنفذ - في (في ذلك الوقت ، الإصدار الأحدث) من nginx 1.13.0 هناك خطأ بسبب بدء اختبار nginx التكوين عبر
nginx -t
واستخدام SO_REUSEPORT
بدأت عملية اختبار nginx هذه حقًا في الاستماع إلى المنفذ 80 واعتراض الطلبات من عملاء حقيقيين . وفي نهاية عملية اختبار التكوين ، تلقى العملاء Connection reset by peer
- وأخيرًا ، عند مراقبة zabbix ، تم تكوين مراقبة صحة تكوين nginx على جميع الخوادم التي تم تثبيت nginx عليها: تم استدعاء الأمر
nginx -t
مرة واحدة في الدقيقة.
فقط بعد تحديث nginx ، يمكنك التنفس بهدوء. ارتفع الرسم البياني لوقت تشغيل المواقع.
ما هو المعنى لهذه القصة كلها؟ كن متفائلًا وتجنب استخدام النوى المجمعة ذاتيًا.