كيف تذهب المحفوظة لدينا الجمعة السوداء

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



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

يسعد العمل بكل هذه الآليات للعمل مع الأسعار ، لكننا نريد التحدث عن الخدمة من وجهة نظر مختلفة قليلاً.

كيف يعمل؟


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

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



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

الجمعة السوداء 2016. ونحن نائم لها


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

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

الخدمة "ذهبت" قبل ساعة من منتصف الليل. بدأ كل شيء مع انقطاع في الاتصال بقاعدة البيانات (MySQL في ذلك الوقت) ، وبعد ذلك لم يكن بإمكان جميع نسخ تشغيل خدمة حساب الأسعار الاتصال مرة أخرى. وأولئك الذين لا يزالون متصلين لم يقاوموا الحمل وتوقفوا عن الاستجابة ، عالقون على أقفال القاعدة.

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

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

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


نتائج الجمعة السوداء 2016

الجمعة السوداء 2017. كنا نستعد بجدية ، ولكن ...


بعد تلقينا درسًا جيدًا ، قمنا بالتحضير مقدمًا لـ "الجمعة السوداء" التالية ، بعد إعادة بناء الخدمة وتحسينها بشكل جدي. على سبيل المثال ، أنشأنا أخيرًا نوعين من الكوبونات: محدود وغير محدود - لتجنب الأقفال على الوصول المتزامن إلى قاعدة البيانات ، أزلنا الإدخال إلى قاعدة البيانات من البرنامج النصي لتطبيق الكوبون الشعبي. بالتوازي مع ذلك ، قبل شهر إلى يومين من يوم الجمعة الأسود ، انتقلنا من MySQL إلى PostgreSQL في الخدمة ، مما أدى ، إلى جانب تحسين الكود ، إلى تقليل عدد مكالمات قاعدة البيانات من 28 إلى 4- 5. سمحت لنا هذه التحسينات بتوسيع خدمة الاختبار إلى متطلبات SLA - الإجابة في 3 ثوان ، 95 في المئة في 600 RPS.

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

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

كانت مهمتنا الرئيسية لخدمة مثل هذه الحركة القيمة للأعمال. لكن أصبح من الواضح أن "الصب بالحديد" لا يحل المشكلة ، ومن أي دقيقة سيصل عدد العمال المشغولين إلى 100٪. بدون معرفة ما الذي واجهناه بالضبط ، قررنا تنشيط الحراكي في uWSGI وببساطة تلبية الطلبات الطويلة (التي تتم معالجتها لأكثر من 6 ثوان) لتحرير الموارد للأغراض العادية. وقد ساعدت حقًا على المقاومة - بدأ إطلاق سراح العمال قبل بضع دقائق من استنفادهم تمامًا.

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

الجمعة السوداء 2018


بحلول عام 2018 ، بالنسبة للخدمات المحملة بشكل كبير والتي تخدم الموقع ، بدأنا تدريجياً في تطبيق Go. بالنظر إلى تاريخ يوم الجمعة الأسود السابق ، كانت خدمة حساب الخصم واحدة من أوائل المرشحين للمعالجة.



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

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

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

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

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

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

"الإعداد" الآخر هو عدد الاتصالات التي يتم الاحتفاظ بها كحفاظ على الحياة. عملاء HTTP و DB العاديين في Go بشكل افتراضي يحتفظان باتصالين فقط ، لذلك إذا كان هناك العديد من الطلبات المتزامنة وتحتاج إلى حفظ حركة مرور إعداد اتصال TCP ، فمن المنطقي زيادة هذه القيمة عن طريق تعيين MaxIdleConnsPerHost و SetMaxIdleConns ، على التوالي.

ومع ذلك ، حتى مع هذه "التقلبات" اليدوية ، زودنا Golang بهامش كبير من الأداء للمبيعات المستقبلية.

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


All Articles