هذا هو واحد من أروع النقوش المشروع. في الصورة - رسم بياني لإجمالي الوقت الذي تقضيه وحدة المعالجة المركزية لمعالجة جميع طلبات المستخدمين. في النهاية يمكنك أن ترى الانتقال إلى PHP 7.0. منذ الإصدار 5.6. هذا هو عام 2016 ، في فترة الظهيرة من 24 نوفمبر.من وجهة نظر العمليات الحسابية ، تعد Tutu.ru في المقام الأول فرصة لشراء تذكرة من النقطة A إلى النقطة B. للقيام بذلك ، نطحن عددًا كبيرًا من الجداول ، ونخزن مؤقتًا استجابات العديد من أنظمة شركات الطيران وننشئ استعلامات ربط طويلة بشكل لا يصدق إلى قاعدة البيانات. بشكل عام ، نحن مكتوبون بلغة PHP وحتى وقت قريب كنا نستخدمها بشكل كامل (إذا تم إعداد اللغة بشكل صحيح ، فيمكنك بناء أنظمة في الوقت الفعلي). في الآونة الأخيرة ، أصبحت المناطق الحرجة للأداء مُعاد تشكيلها على Go.
لدينا باستمرار الديون التقنية . وهذا يحدث بشكل أسرع مما نود. الخبر السار: ليس عليك تغطية كل شيء. غير صحيح: مع نمو الوظائف المدعومة ، ينمو الدين الفني أيضًا بالتناسب.
بشكل عام ، الدين التقني هو تكلفة ارتكاب خطأ في اتخاذ القرار. لم تتوقع شيئًا مثل المعماري ، أي أنك ارتكبت خطأً في التنبؤ أو اتخذت قرارًا في ظروف عدم كفاية المعلومات. في مرحلة ما ، تفهم أنك بحاجة إلى تغيير شيء ما في الكود (غالبًا على مستوى الهندسة المعمارية). ثم يمكنك التغيير على الفور ، ولكن يمكنك الانتظار. إذا كنت تنتظر - هرع الفائدة إلى الدين التكنولوجيا. لذلك ، من الممارسات الجيدة إعادة هيكلتها من وقت لآخر. حسنًا ، أو أعلن إفلاسك واكتب المجموعة بأكملها مرة أخرى.
كيف بدأ كل شيء: وظائف متراصة وعامة
بدأ مشروع Tutu.ru في عام 2003 كموقع دوري على الإنترنت في تلك الأوقات. أي أنها كانت مجموعة من الملفات بدلاً من قاعدة بيانات ، صفحة PHP في مقدمة HTML + JS. كان هناك اثنين من الاختراقات الممتازة من زميلي يوري ، لكنه من الأفضل أن يخبره يومًا ما. انضممت إلى المشروع في عام 2006 ، أولاً كمستشار خارجي يمكن أن يساعد في تقديم المشورة والرمز ، ثم في عام 2009 ، انتقلت إلى الولاية كمدير فني. بادئ ذي بدء ، كان من الضروري ترتيب الأمور في اتجاه تذاكر الطيران: كان الجزء الأكثر تحميلًا والأكثر تعقيدًا في الهندسة المعمارية.
في عام 2006 ، أذكرك أنه كان هناك جدول زمني للقطار وكانت هناك فرصة لشراء تذكرة قطار. قررنا أن نجعل قسم تذاكر الطيران كمشروع منفصل ، أي أنه تم توحيد كل هذا فقط في المقدمة. جميع المشاريع الثلاثة (جداول القطارات والسكك الحديدية والجو) تمت كتابتها في النهاية بطريقتها الخاصة. في ذلك الوقت ، بدا الرمز طبيعيًا بالنسبة لنا ، لكنه لم يكتمل إلى حد ما. Neperfektsionistskim. ثم حصل على العمر ، وغطى نفسه بالعكازات وفي اتجاه السكك الحديدية تحول إلى قرع بحلول عام 2010.
في السكك الحديدية ، لم يكن لدينا وقت لإعطاء الدين التقني. إعادة البناء كانت غير واقعية: كانت المشاكل في العمارة. قررنا هدم وإعادة كل شيء من جديد ، لكن كان من الصعب أيضًا على مشروع مباشر. نتيجةً لذلك ، تم ترك عناوين URL القديمة فقط في المقدمة ، ثم تمت إعادة كتابة الحظر من كتلة. كأساس ، اتخذنا النهج المستخدمة قبل عام في تطوير قطاع الطيران.
إعادة كتابة في PHP. ثم كان من الواضح أن هذا لم يكن هو السبيل الوحيد ، ولكن لم تكن هناك بدائل معقولة لنا. لقد اختاروا ذلك لأن لديهم بالفعل خبرة وإنجازات ، وكان من الواضح أن هذه لغة جيدة في أيدي كبار المطورين. من بين البدائل ، كانت C و C ++ مثمرة ، لكن أي إعادة بناء أو إدخال تغييرات عليها كانت تشبه الكابوس. حسنا ، ليس تذكير. كان كابوسا.
لم يتم النظر حتى MS وجميع NET من وجهة نظر مشروع تحميل عالية. ثم لم تكن هناك خيارات أخرى غير نظام Linux على الإطلاق. تعد Java خيارًا جيدًا ، ولكنها تتطلب موارد من الذاكرة ، ولا تسامح أبدًا عن الأخطاء المبتدئة ، ثم لم تسمح بإصدار الإصدارات بسرعة - حسنًا ، أو لم نعرف ذلك. حتى الآن نحن لا نعتبر Python كواجهة خلفية ، فقط لمهام معالجة البيانات. شبيبة - بحتة تحت الجبهة. لم يكن هناك روبي على Rails المطورين ثم (والآن). ذهب ذهب. كان لا يزال هناك بيرل ، لكن الخبراء صنفوها على أنها غير واعدة لتطوير الويب ، لذا فقد تخلوا عنها. يتم ترك PHP.
قصة holiv التالية هي PostgreSQL مقابل MySQL. مكان أفضل واحد ، في مكان آخر. بشكل عام ، كان من الممارسات الجيدة اختيار ما تبين بشكل أفضل ، لذلك اخترنا MySQL وشوكاته.
كان نهج التطوير مترابطًا ، ثم لم تكن هناك منهجيات أخرى ، ولكن مع البنية المتعامدة للمكتبات. هذه هي بدايات النهج الحديث المتمحور حول واجهة برمجة التطبيقات ، عندما يكون لكل مكتبة واجهة في الخارج ، والتي يمكنك سحبها مباشرة داخل الكود من أجزاء أخرى من المشروع. تمت كتابة المكتبات في "طبقات" عندما يكون لكل مستوى تنسيق معين عند الإدخال ويمرر تنسيقًا معينًا إلى أبعد من الكود ، وتدور اختبارات الوحدة بينهما. وهذا هو ، شيء من هذا القبيل تطوير يحركها الاختبار ، ولكن منقطة ومخيفة.
كل هذا تم استضافته على عدة خوادم ، مما جعل من الممكن التوسع تحت الحمل. ولكن في الوقت نفسه ، تتقاطع قاعدة الكود الخاصة بمشاريع مختلفة بقوة على مستوى النظام. هذا يعني في الواقع أن التغييرات في مشروع السكك الحديدية يمكن أن تؤثر على طائراتنا. ولمس كثيرا. على سبيل المثال ، في السكك الحديدية كان من الضروري توسيع نطاق العمل مع المدفوعات - وهذا هو مراجعة للمكتبة المشتركة. والطائرة تعمل معها ، لذلك ، هناك حاجة لاختبار مشترك. نحن فحص التبعيات مع الاختبارات ، وكان هذا أكثر أو أقل طبيعية. حتى في عام 2009 ، كانت الطريقة متقدمة للغاية. ولكن لا يزال ، يمكن أن تضيف الحمل أخرى من مورد واحد. كان هناك تقاطع في قواعد البيانات ، مما أدى إلى آثار غير سارة في شكل الفرامل في جميع أنحاء الموقع مع المشاكل المحلية في منتج واحد. قتل السكك الحديدية الطائرة عدة مرات على القرص بسبب استفسارات ثقيلة إلى قاعدة البيانات.
نحن تحجيمها بإضافة الحالات والتوازن بينهما. متراصة كما هي.
عمر الإطارات
ثم ذهبنا على طريق هامشي إلى حد ما. من ناحية ، بدأنا في عزل الخدمات (اليوم ، يُطلق على هذا النهج اسم microservice ، لكننا لم نكن نعرف كلمة "micro") ، ولكن للتفاعل بدأنا في استخدام الناقل لنقل البيانات ، بدلاً من REST أو gRPC ، كما هو الحال الآن. اخترنا AMQP كبروتوكول ، و RabbitMQ كوسيط للرسائل. بحلول ذلك الوقت ، كنا قد أتقننا إطلاق إطلاق الشياطين لـ PHP (نعم ، هناك شوكة تعمل بالكامل) وكل شيء آخر للعمل مع العمليات) ، لأننا لفترة طويلة في المونولث استخدمنا شيئًا مثل Gearman لموازنة الطلبات مع أنظمة الحجز .
لقد صنعوا وسيطًا على رأس الأرنب ، واتضح أن كل هذا لا يعيش حقًا تحت الحمل. نوع من خسائر الشبكة ، يعيد إرسال ، والتأخير. على سبيل المثال ، تعمل مجموعة من الوسطاء "خارج الصندوق" بشكل مختلف نوعًا ما عن سلوك المطور (لم يحدث هذا من قبل ، ومرة أخرى). بشكل عام ، لقد تعلموا الكثير. لكن في النهاية ، حصلنا على اتفاقيات مستوى الخدمة المطلوبة للخدمات. على سبيل المثال ، تحتوي خدمة RPS الأكثر تحميلًا على 400 دورة في الثانية ، وهي الجولة المئوية التاسعة والتسعين من العميل إلى العميل ، بما في ذلك معالجة الحافلة والخدمة بقيمة 35 مللي ثانية. الآن بشكل إجمالي على الحافلة نلاحظ حوالي 18 كيلو بايت في الثانية.
ثم جاء اتجاه الحافلات. لقد كتبنا على الفور دون متراصة على بنية الخدمة. نظرًا لأن كل شيء تم كتابته من نقطة الصفر ، فقد أصبح جيدًا وسريعًا ومريحًا ، على الرغم من أنه كان من الضروري صقل الأدوات باستمرار لنهج جديد. نعم ، كل هذا كان يدور على أجهزة افتراضية ، من خلالها تتواصل شياطين PHP عبر الحافلة. بدأت الشياطين داخل حاويات Docker ، لكن لم تكن هناك حلول للتنسيق مثل Openshift أو Kubernetes. في عام 2014 ، بدأنا للتو الحديث عن ذلك ، لكننا لم نفكر في مثل هذا النهج في المبيعات.
إذا قارنت عدد تذاكر الحافلة التي يتم بيعها بالمقارنة مع تذاكر الطائرة أو القطار ، فستحصل على انخفاض في المجموعة. وفي القطارات والطائرات ، كان الانتقال إلى بنية جديدة أمرًا صعبًا ، لأن هناك وظيفة وظيفية وحمل حقيقي ، وكان هناك دائمًا خيار بين القيام بشيء جديد أو إنفاق أموال على سداد دين تقني.
يعد الانتقال إلى الخدمات أمرًا جيدًا ، ولكنه شيء طويل ، لكنك تحتاج إلى التعامل مع العبء والموثوقية الآن. لذلك ، بالتوازي ، بدأوا في اتخاذ تدابير هادفة لتحسين حياة المتراصة. تم تقسيم الجوانب الخلفية إلى أنواع المنتجات ، أي أنها بدأت في التحكم بشكل أكثر مرونة في توجيه الطلبات وفقًا لنوعها: الهواء بشكل منفصل عن السكك الحديدية ، وما إلى ذلك. كان من الممكن التنبؤ بالتحميل ، والقياس بشكل مستقل. عندما عرفوا أنه في السكك الحديدية ، على سبيل المثال ، بلغت ذروة مبيعات السنة الجديدة ، ثم تم إضافة العديد من الحالات من الأجهزة الافتراضية. ثم بدأ بعد 45 يومًا تمامًا من آخر يوم عمل من العام ، وفي الفترة من 14 إلى 15 نوفمبر ، كان لدينا حمولة مزدوجة. الآن قامت FPK وشركات الطيران الأخرى بعمل العديد من التذاكر مع بدء المبيعات في 60 و 90 وحتى 120 يومًا ، وانتشرت هذه الذروة. ولكن في يوم العمل الأخير من شهر أبريل ، سيكون هناك دائمًا حمولة على القطارات الكهربائية قبل شهر أيار (مايو) ، ولا تزال هناك قمم. ولكن فيما يتعلق بموسمية التذاكر وطرق هجرة التسريح ، فإن زملائي من السكك الحديدية سيخبرونني بشكل أفضل ، وسأواصل عن الهندسة المعمارية.
في مكان ما في عام 2014 ، بدأوا في derban قاعدة بيانات كبيرة من العديد من تلك الصغيرة. كان هذا مهمًا لأنه كان ينمو بشكل خطير ، وكان السقوط حرجًا. بدأنا في اختيار قواعد بيانات صغيرة منفصلة (للجداول من 5 إلى 10) للحصول على وظيفة محددة ، بحيث تؤثر الخدمات الأخرى على عدد أقل من الاضطرابات ، وبالتالي يمكن توسيع نطاق كل هذا. تجدر الإشارة إلى أنه لموازنة التحميل والقياس استخدمنا النسخ المتماثلة للقراءة. قد يستغرق استرداد النسخ المتماثلة لقاعدة كبيرة بعد فشل النسخ المتماثل ساعات ، وكان علي طوال هذا الوقت "الطيران على الإفراج المشروط وعلى أحد الأجنحة". ذكريات هذه الفترات لا تزال تسبب البرد غير سارة في مكان ما بين الأذنين. الآن لدينا حوالي 200 حالة من قواعد مختلفة ، وإدارة العديد من المنشآت بأيدينا هي عمل شاق وغير موثوق بها. لذلك ، نحن نستخدم Github Orchestrator ، الذي يقوم بأتمتة العمل باستخدام النسخ المتماثلة و proxySql لتوزيع التحميل والحماية من فشل قاعدة بيانات معينة.
مثل الان
بشكل عام ، بدأنا تدريجياً في تخصيص المهام غير المتزامنة وفصل عمليات الإطلاق في معالج الأحداث حتى لا يتداخل أحدها مع الآخر.
عندما خرج PHP 7 ، شهدنا في الاختبارات تقدمًا كبيرًا للغاية في الأداء وتقليل استهلاك الموارد. تم الانتقال إلى المشروع مع وجود القليل من البواسير ، استغرق المشروع بأكمله من بداية الاختبارات إلى الترجمة الكاملة للإنتاج بأكمله أكثر من ستة أشهر بقليل ، ولكن بعد ذلك انخفض استهلاك الموارد بمقدار النصف تقريبًا. الجدول الزمني للتحميل وحدة المعالجة المركزية - في الجزء العلوي من آخر.
نجا متراصة حتى يومنا هذا ، وفي تقديري ، ما يقرب من 40 ٪ من قاعدة الكود. تجدر الإشارة إلى أن مهمة استبدال المتراصة بأكملها بالخدمات لم يتم تعيينها بشكل صريح. إننا نتحرك بشكل عملي: كل شيء جديد يتم على خدمات microservices ، ولكن إذا كنت بحاجة إلى تحسين الوظيفة القديمة في متراصة ، فنحن نحاول نقلها إلى بنية الخدمة ، إذا لم تكن التحسينات صغيرة جدًا حقًا. في الوقت نفسه ، تتم تغطية المتراصة في الاختبارات حتى نتمكن من نشر مرتين في الأسبوع مع مستوى كاف من الجودة. يتم تغطية الميزات بطرق مختلفة ، اختبارات الوحدات كاملة تمامًا ، اختبارات واجهة المستخدم واختبارات القبول تغطي وظائف البوابة بأكملها تقريبًا (لدينا حوالي 15000 حالة اختبار) ، اختبارات واجهة برمجة التطبيقات (API) كاملة إلى حد ما. نحن تقريبا لا تفعل اختبار الحمل. بتعبير أدق ، يشبه التدريج لدينا الهيكل الزائد ، ولكن ليس في القوة ، وهو محاط بنفس المراقبة. نقوم بإنشاء حمل ، إذا رأينا أن الإصدار السابق على الإصدار القديم يختلف في التوقيت ، فنحن ننظر إلى مدى أهميته. إذا كان الإصدار الجديد والقديم متماثلان تقريبًا ، فسنصدرهما في المنتج. على أي حال ، فإن جميع الميزات تخرج تحت المفتاح بحيث يمكنك إيقاف تشغيلها في أي لحظة إذا حدث خطأ ما.
يتم اختبار الميزات الثقيلة دائمًا بنسبة 1٪ من المستخدمين. ثم نذهب إلى 2 ٪ ، 5 ٪ ، 10 ٪ ، وبالتالي نصل إلى جميع المستخدمين. وهذا يعني أنه يمكننا دائمًا رؤية الحمل غير العادي قبل أن تؤدي الطفرة إلى مقتل الخوادم وفصلها مقدمًا.
عند الضرورة ، أخذنا (وسوف نستغرق) من 4 إلى 5 أشهر لمشروع إعادة هندسة ، عندما يركز الفريق على مهمة محددة. هذه طريقة جيدة لتقليص عقدة Gordian عندما لا تساعد إعادة التوطين المحلية. لقد فعلنا ذلك قبل بضع سنوات بالهواء: قمنا بإعادة تصميم الهيكل ، وقمنا به - حصلنا على الفور على تسارع فوري في التطوير ، وتمكنا من إطلاق العديد من الميزات الجديدة. بعد شهرين من إعادة الهندسة ، زاد عدد العملاء بمقدار كبير بسبب الميزات. لقد بدأوا في إدارة الأسعار بشكل أكثر دقة ، وربط الشركاء ، وأصبح كل شيء أسرع. الفرح. يجب أن أقول ، لقد حان الوقت الآن لفعل الشيء نفسه مرة أخرى ، ولكن هذا هو القدر: طرق بناء التطبيقات تتغير ، حلول جديدة ، أساليب ، أدوات. للبقاء في العمل ، تحتاج إلى النمو.
المهمة الرئيسية لإعادة هندسة بالنسبة لنا هي تسريع التنمية. إذا لم تكن هناك حاجة جديدة ، فإن إعادة الهندسة ليست ضرورية. لا حاجة لاختراع واحدة جديدة: لا معنى للاستثمار في التحديث. وهكذا ، مع الحفاظ على رصة وهندسة معمارية حديثة ، يباشر الأشخاص أعمالهم بشكل أسرع ، ويتصل أحدهم الجديد بشكل أسرع ، ويتصرف النظام بشكل أكثر توقعًا ، حيث يهتم المطورون بالعمل في مشروع ما. الآن هناك مهمة لإنهاء المتراصة دون التخلص منها بالكامل ، بحيث يمكن لكل منتج تحميل التحديثات ، وليس اعتمادًا على الآخرين. وهذا هو ، الحصول على CI / CD معين في متراصة.
نستخدم اليوم ليس فقط الأرنب ، ولكن أيضًا REST و gRPC لتبادل المعلومات بين الخدمات. تتم كتابة بعض الخدمات المجهرية في Golang: السرعة الحسابية ومعالجة الذاكرة ممتازة هناك. كانت هناك دعوة لتنفيذ دعم nodeJS ، ولكن في النهاية تركنا العقدة فقط لتقديم الخادم ، وترك منطق العمل في PHP و Go. من حيث المبدأ ، يسمح لنا النهج المختار بتطوير الخدمات بأي لغة تقريبًا ، لكننا قررنا الحد من حديقة الحيوان حتى لا نزيد من تعقيد النظام.
نذهب الآن إلى خدمات micros من شأنها أن تعمل في حاويات Docker تحت تزامن OpenShift. المهمة في غضون سنة ونصف - 90 ٪ من كل تطور داخل المنصة. لماذا؟ لذلك ، يتم نشرها بشكل أسرع وأسرع للتحقق من الإصدارات ، وهناك فرق أقل في البيع من بيئة التطوير. يمكن للمطور أن يفكر أكثر في الميزة التي ينفذها ، وليس حول كيفية نشر البيئة ، وكيفية تكوينها ، ومن أين تبدأ ، أي فائدة أكبر. مرة أخرى - المشكلات التشغيلية: هناك العديد من الخدمات المصغرة ، وهي بحاجة إلى أتمتة من قبل الإدارة. يدويًا - التكاليف المرتفعة جدًا ، ومخاطر الأخطاء مع التحكم اليدوي ، والمنصة تعطي تحجيمًا طبيعيًا.
كل عام لدينا زيادة في عبء العمل - بنسبة 30-40 ٪: المزيد والمزيد من الناس يتقنون الحيل مع الإنترنت ، والتوقف عن الذهاب إلى مكاتب النقد المادية ، ونحن نضيف منتجات وميزات جديدة لتلك الموجودة. الآن يأتي حوالي مليون مستخدم يوميًا إلى البوابة. بالطبع ، ليس كل المستخدمين يولدون نفس الحمل. لا يحتاج شيء إلى موارد حسابية على الإطلاق ، وعلى سبيل المثال ، تعتبر عمليات البحث مكونًا كثيف الاستخدام للموارد. هناك ، يؤدي وضع علامة واحدة "زائد أو ناقص ثلاثة أيام" في مجال الطيران إلى زيادة الحمل بمقدار 49 مرة (عند النظر إلى الأمام والخلف ، تكون المصفوفة 7 في 7). كل شيء آخر بالمقارنة مع البحث عن تذكرة داخل أنظمة السكك الحديدية والهواء بسيط للغاية. أسهل شيء في الموارد هو
البحث عن المغامرة والجولات (لا يوجد أسهل ذاكرة تخزين مؤقت من حيث الهندسة المعمارية ، ولكن لا يزال هناك عدد أقل بكثير من الجولات من مجموعات التذاكر) ، ثم
جدول القطار (يتم تخزينه مؤقتًا بسهولة بواسطة الوسائل القياسية) ، وعندها فقط كل شيء آخر .
بالطبع ، لا يزال الدين الفني يتراكم. من جميع الجهات. الشيء الرئيسي هو أن نفهم في الوقت المناسب حيث يمكنك إدارة refactor ، وكل شيء سيكون على ما يرام ، حيث لا تضطر إلى لمس أي شيء (في بعض الأحيان يحدث ذلك: نحن نعيش مع ليجاسي إذا لم تكن هناك تغييرات المخطط لها) ، ولكن في مكان ما نحن بحاجة إلى التسرع وإعادة هندسة أنفسنا ، لأنه بدون هذا المستقبل لن يكون. بالطبع ، نحن نرتكب أخطاء ، ولكن بشكل عام ، لقد كان Tutu.ru موجودًا منذ 16 عامًا ، وأنا أحب ديناميكيات المشروع.