توثيق هابروكسي يتجول في السجل ، أو ما الذي تبحث عنه عند تكوينه

مرحبا مرة أخرى!

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



تكوين هابروكسي


كانت الصعوبة الأولى هي أن خيار maxconn يختلف باختلاف السياق:


خارج العادة ، لقد ضبطت الخيار الأول فقط ( performance tuning ). إليك ما تقوله الوثائق حول هذا الخيار:
يضبط الحد الأقصى لكل عملية من الاتصالات المتزامنة على <number>. ذلك
يكافئ وسيطة سطر الأوامر "-n". سيتوقف الوكلاء عن القبول
اتصالات عند الوصول إلى هذا الحد.

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

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

عظيم ، ما تحتاجه. إضافة إلى التكوين:

 global daemon maxconn 524288 ... defaults mode http maxconn 524288 

كان الكمامة التالية هي أن هابروكسي مترابط. أنا معتاد جدًا على النموذج الموجود في Nginx ، لذا فإن هذه الفروق الدقيقة كانت تحبطني دائمًا. ولكن لا تيأس - فهم ويلي تاريو ( مطور هابروكسي ) ما كان يفعله ، لذلك أضاف الخيار - nbproc .

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

  • تحديد عدد الطلبات / الاتصالات بالخوادم (حيث لن يكون لديك بالفعل عملية واحدة بمقياس واحد ، ولكن العديد من العمليات ، ولكل منها عداد خاص بها) ؛
  • جمع الإحصاءات من مأخذ توصيل إدارة Haproxy
  • تمكين / تعطيل الواجهة الخلفية من خلال مقبس التحكم ؛
  • ... ربما شيء آخر. ¯ \ _ (ツ) _ / ¯

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

  nbproc 4 cpu-map 1 0 cpu-map 2 1 cpu-map 3 2 cpu-map 4 3 

باستخدام cpu-map ، نربط عمليات Haproxy بنواة معينة. لم تعد أداة جدولة نظام التشغيل بحاجة إلى التفكير في مكان التخطيط لـ Haproxy ، وبالتالي الحفاظ على رمز content switch باردًا وذاكرة التخزين المؤقت لوحدة المعالجة المركزية.

هناك العديد من المخازن المؤقتة ، ولكن ليس في حالتنا


  • tune.bufsize - في حالتنا ، لم يكن من الضروري تشغيلها ، ولكن إذا كانت لديك أخطاء في الكود 400 (Bad Request) غير صحيح 400 (Bad Request) ، فمن المحتمل أن يكون هذا هو حالتك.
  • tune.http.cookielen - إذا قمت بتوزيع ملفات تعريف الارتباط الكبيرة على المستخدمين ، فمن أجل تجنب التلف أثناء النقل عبر الشبكة ، قد يكون من المنطقي رفع هذا المخزن المؤقت أيضًا.
  • tune.http.maxhdr هو مصدر آخر محتمل لرموز الاستجابة 400 إذا كان لديك الكثير من الرؤوس.

الآن النظر في الاشياء مستوى أدنى


tune.rcvbuf.client / tune.rcvbuf.server ، tune.sndbuf.client / tune.sndbuf.server - تقول الوثائق ما يلي:
يجب ألا يتم تعيينها عادةً ، والحجم الافتراضي (0) يسمح للنواة بضبط هذه القيمة اعتمادًا على مقدار الذاكرة المتوفرة.

لكن بالنسبة لي ، فالواضح أفضل من الضمني ، لذلك أجبرت قيم هذه الخيارات على التأكد من الغد.

والمعلمة الأخرى التي لا تتعلق المخازن المؤقتة ، ولكن المهم للغاية هو tune.maxaccept .
يضبط الحد الأقصى لعدد الاتصالات المتتالية التي قد تقبلها العملية في
الصف قبل التحول إلى أعمال أخرى. في وضع عملية واحدة ، وأرقام أعلى
إعطاء أداء أفضل بمعدلات اتصال عالية. لكن في عملية متعددة
وسائط ، والحفاظ على القليل من العدالة بين العمليات عموما من الأفضل أن
زيادة الأداء.

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

جميع المعلمات معا:

  tune.bufsize 16384 tune.http.cookielen 63 tune.http.maxhdr 101 tune.maxaccept 256 tune.rcvbuf.client 33554432 tune.rcvbuf.server 33554432 tune.sndbuf.client 33554432 tune.sndbuf.server 33554432 

ما لم يحدث أبدا هو مهلات. ماذا سنفعل بدونهم؟


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

Kulstory حول عميل HTTP في Go
لدى Go عميل HTTP عادي لديه القدرة على الاحتفاظ بمجموعة من الاتصالات بالخوادم. لذلك حدث قصة واحدة مثيرة للاهتمام ، والتي شارك فيها المهلة المذكورة أعلاه وتجمع الاتصال في عميل HTTP. بمجرد أن اشتكى أحد المطورين من أنه لديه 408 أخطاء من الخادم الوكيل بشكل دوري. نظرنا في كود العميل ورأينا المنطق التالي هناك:

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

فهمت بالفعل ما هو الملح؟

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

  • خادم المهلة - الحد الأقصى لوقت انتظار استجابة الخادم.
  • timeout client-fin / timeout server-fin - نحن هنا نحمي أنفسنا من الاتصالات نصف المغلقة حتى لا نجمعها في جدول نظام التشغيل.
  • مهلة طلب HTTP هي واحدة من أنسب المهلات. يتيح لك إيقاف العملاء البطيئين الذين لا يمكنهم تقديم طلب HTTP في الوقت المخصص لهم.
  • مهلة http-keep-alive - على وجه التحديد في حالتنا ، إذا توقف اتصال keep-alive دون طلبات لأكثر من 50 ثانية ، فمن المحتمل أن يكون هناك خطأ ما ويمكن إغلاق الاتصال ، وبالتالي تحرير الذاكرة لشيء جديد الضوء.

جميع المهلات معا:

 defaults mode http maxconn 524288 timeout connect 5s timeout client 10s timeout server 120s timeout client-fin 1s timeout server-fin 1s timeout http-request 10s timeout http-keep-alive 50s 

تسجيل لماذا هو معقد جدا؟


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

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

 #  ,     ,    (   # error.log  nginx) log 127.0.0.1:2514 len 8192 local1 notice emerg #    -  access.log log 127.0.0.1:2514 len 8192 local7 info 

الألم الناجم عن مثل هذه اللحظات:
  • أسماء المتغيرات القصيرة ، وخاصة مجموعاتها مثل٪ HU أو٪ fp
  • لا يمكن تقسيم التنسيق إلى عدة أسطر ، لذا يجب عليك كتابة footcloth في سطر واحد. من الصعب إضافة / إزالة عناصر جديدة / غير ضرورية
  • لكي تعمل بعض المتغيرات ، يجب الإعلان عنها بوضوح من خلال رأس طلب الالتقاط

نتيجة لذلك ، للحصول على شيء مثير للاهتمام ، يجب أن يكون لديك مثل هذه القاعدة:

 log-format '{"status":"%ST","bytes_read":"%B","bytes_uploaded":"%U","hostname":"%H","method":"%HM","request_uri":"%HU","handshake_time":"%Th","request_idle_time":"%Ti","request_time":"%TR","response_time":"%Tr","timestamp":"%Ts","client_ip":"%ci","client_port":"%cp","frontend_port":"%fp","http_request":"%r","ssl_ciphers":"%sslc","ssl_version":"%sslv","date_time":"%t","http_host":"%[capture.req.hdr(0)]","http_referer":"%[capture.req.hdr(1)]","http_user_agent":"%[capture.req.hdr(2)]"}' 

حسنا ، يبدو ، أشياء صغيرة ، ولكن لطيفة


وصفت شكل السجل أعلاه ، ولكن ليس بهذه البساطة. لإيداع بعض العناصر فيه ، مثل:

  • http_host
  • http_referer ،
  • http_user_agent ،

تحتاج أولاً إلى التقاط هذه البيانات من الطلب ( الالتقاط ) ووضعها في مجموعة من القيم الملتقطة.

هنا مثال:

 capture request header Host len 32 capture request header Referer len 128 capture request header User-Agent len 128 

نتيجةً لذلك ، يمكننا الآن الوصول إلى العناصر التي نحتاجها بهذه الطريقة:
%[capture.req.hdr(N)] ، حيث N هو رقم التسلسل لتعريف مجموعة الالتقاط.
في المثال أعلاه ، سيكون رأس المضيف في الرقم 0 ، وسيكون وكيل المستخدم في الرقم 2.

تتمتع Haproxy بخصوصية: فهي تحل عناوين DNS للواجهات الخلفية عند بدء التشغيل ، وإذا لم تتمكن من حل أي من العناوين ، فتقع وفاة الشجعان.

في حالتنا ، هذا ليس ملائمًا للغاية ، نظرًا لوجود الكثير من النهايات الخلفية ، لا نديرها ، ومن الأفضل الحصول على 503 من Haproxy مما سيرفض الخادم الوكيل بأكمله بدء التشغيل بسبب مزود واحد. الخيار التالي يساعدنا في هذا: init-addr .

يسمح لنا سطر مأخوذ مباشرةً من الوثائق بالاطلاع على جميع الطرق المتاحة لحل عنوان ما ، وفي حالة وجود ملف ، قم فقط بتأجيل هذه المسألة إلى وقت لاحق والمتابعة:

 default-server init-addr last,libc,none 

وأخيرا ، المفضل لدي: اختيار الخلفية.
بناء الجملة لتكوين تحديد الواجهة الخلفية Haproxy مألوف للجميع:

 use_backend <backend1_name> if <condition1> use_backend <backend2_name> if <condition2> default-backend <backend3> 

ولكن ، الكلمة الصحيحة ، ليست بطريقة أو بأخرى. لقد سبق أن وصفت جميع الخلفية بطريقة تلقائية (راجع المقال السابق ) ، سيكون من الممكن توليد use_backend هنا use_backend ، use_backend السيئ ليس خادعًا ، لكنني لم أرغب في ذلك. نتيجة لذلك ، تم العثور على طريقة أخرى:

  capture request header Host len 32 capture request header Referer len 128 capture request header User-Agent len 128 #   host_present      Host acl host_present hdr(host) -m len gt 0 #    ,     use_backend %[req.hdr(host),lower,field(1,'.')] if host_present #      ,    default_backend default backend default mode http server no_server 127.0.0.1:65535 

وبالتالي ، قمنا بتوحيد أسماء الخلفية وعناوين URL التي يمكنك من خلالها الانتقال إليهم.

حسنا ، الآن تجميع من الأمثلة المذكورة أعلاه في ملف واحد:

النسخة الكاملة من التكوين
  global daemon maxconn 524288 nbproc 4 cpu-map 1 0 cpu-map 2 1 cpu-map 3 2 cpu-map 4 3 tune.bufsize 16384 tune.comp.maxlevel 1 tune.http.cookielen 63 tune.http.maxhdr 101 tune.maxaccept 256 tune.rcvbuf.client 33554432 tune.rcvbuf.server 33554432 tune.sndbuf.client 33554432 tune.sndbuf.server 33554432 stats socket /run/haproxy.sock mode 600 level admin log /dev/stdout local0 debug defaults mode http maxconn 524288 timeout connect 5s timeout client 10s timeout server 120s timeout client-fin 1s timeout server-fin 1s timeout http-request 10s timeout http-keep-alive 50s default-server init-addr last,libc,none log 127.0.0.1:2514 len 8192 local1 notice emerg log 127.0.0.1:2514 len 8192 local7 info log-format '{"status":"%ST","bytes_read":"%B","bytes_uploaded":"%U","hostname":"%H","method":"%HM","request_uri":"%HU","handshake_time":"%Th","request_idle_time":"%Ti","request_time":"%TR","response_time":"%Tr","timestamp":"%Ts","client_ip":"%ci","client_port":"%cp","frontend_port":"%fp","http_request":"%r","ssl_ciphers":"%sslc","ssl_version":"%sslv","date_time":"%t","http_host":"%[capture.req.hdr(0)]","http_referer":"%[capture.req.hdr(1)]","http_user_agent":"%[capture.req.hdr(2)]"}' frontend http bind *:80 http-request del-header X-Forwarded-For http-request del-header X-Forwarded-Port http-request del-header X-Forwarded-Proto capture request header Host len 32 capture request header Referer len 128 capture request header User-Agent len 128 acl host_present hdr(host) -m len gt 0 use_backend %[req.hdr(host),lower,field(1,'.')] if host_present default_backend default backend default mode http server no_server 127.0.0.1:65535 resolvers dns hold valid 1s timeout retry 100ms nameserver dns1 127.0.0.1:53 


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

اراك قريبا!

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


All Articles