توقف اليوم دودو. النصي متزامن

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

لكن الآن ننام بشكل أفضل. لقد تعلمنا التعرف على سيناريوهات نهاية العالم النظامية ومعالجتها. أدناه سوف أخبرك كيف نوفر استقرار النظام.

سلسلة من المقالات حول انهيار نظام Dodo IS * :
1. اليوم توقف دودو. النصي متزامن.
2. اليوم الذي توقف فيه دودو. نص غير متزامن.

* تمت كتابة المواد بناءً على أدائي في DotNext 2018 في موسكو .

دودو هو


يعد النظام ميزة تنافسية كبيرة لامتيازنا ، لأن أصحاب الامتياز يحصلون على نموذج أعمال جاهز. هذه هي ERP ، HRM و CRM ، الكل في واحد.

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

أداء النظام


دودو أداء النظام = الموثوقية = خطأ التسامح / الاسترداد. دعونا نتناول كل نقطة من النقاط.

الموثوقية


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

خطأ التسامح


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

المرونة


فشل المكونات الفردية تحدث كل يوم. هذا طبيعي. من المهم مدى سرعة تعافينا من الفشل.

سيناريو فشل النظام المتزامن


ما هذا


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

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

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

لخدمة العديد من الطلبات ، نحتاج إلى الخيار الصحيح:



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

يمكن توضيح المهام المتعددة المبسطة وقائية على النحو التالي:



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

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

النظر في نتائج اختبار الاصطناعية:



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

فكر في الأمر ، في السحابة طلبت آلة افتراضية مع 72 مركزًا. يكلف مالاً ، وتستخدم أقل من نصف الأساسية. هذا هو بالضبط ما يمكن أن يحدث في تطبيق متعدد الخيوط.

إذا كان هناك عدد أقل من المهام ، ولكن مدتها أطول ، تزداد الكفاءة. نرى أنه في 5000 عملية في الثانية ، في كلتا الحالتين تكون الكفاءة 80-90 ٪. بالنسبة للنظام متعدد المعالجات ، هذا جيد جدًا.



في تطبيقاتنا الحقيقية ، تكمن مدة العملية الواحدة بين المزامنة في مكان ما بينهما ، وبالتالي فإن المشكلة ملحة.

ما الذي يحدث؟


إيلاء الاهتمام لنتائج اختبار الإجهاد. في هذه الحالة ، كان ما يسمى "اختبار البثق".



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

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



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

طرق لإيجاد مشكلة


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

أقفال في العملية


إليك طلب نموذجي في تطبيق الحظر.

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

دعونا نرى كيف تحجيم.

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

سنقاتل بهذه الطريقة.
var fallback = FallbackPolicy<OptionalData> .Handle<OperationCancelledException>() .FallbackAsync<OptionalData>(OptionalData.Default); var optionalDataTask = fallback .ExecuteAsync(async () => await CalculateOptionalDataAsync()); //… var required = await CalculateRequiredData(); var optional = await optionalDataTask; var price = CalculatePriceAsync(optional, required); 

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

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

أقفال DB


نحصل على نفس التصميم تقريبًا عندما نعيد كتابته على المتزامن ونغير نموذج التناسق.

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


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

تزامن IO


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


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

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

كل شيء سيء للغاية


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

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

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

هذا يثير السؤال - هل من الضروري إعادة كتابة؟

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

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

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


All Articles