صوت البازار
نشرت: 2024-04-24تعد هذه المقالة حول تحديث الأنظمة القديمة جزءًا مصاحبًا للمحاضرة التي قدمتها مؤخرًا في AWS Data Summit لشركات البرمجيات حول توليد القيمة من البيانات من خلال الاستفادة من أفضل ممارساتنا لضمان النجاح في مشاريع التعلم الآلي. يمكنك القفز إلى الأسفل هنا لمشاهدته إذا كنت تفضل ذلك.
دعونا نواجه الأمر: كتابة البرامج أسهل من صيانتها. ولهذا السبب، فإننا، كمهندسي برمجيات، نفضل "إزالة كل شيء والبدء من جديد" بدلاً من محاولة فهم ما كان يفكر فيه مطور آخر (أو ماضينا). يبدو أننا نسينا بشكل جماعي أن "البرامج يجب أن تُكتب ليقرأها الناس، وبالمصادفة فقط لكي تنفذها الآلات".
أنت تعلم أن هذا صحيح - لقد كان علينا جميعًا أن نتتبع بشق الأنفس من خلال وعاء من كود السباغيتي وتجريدات رفيعة على طراز العالم القديم للبحث عن لحم البرنامج فقط لنجد شيئًا سوى الفوضى في الجزء السفلي من أطباقنا.
من السهل الصراخ "WTF" وإلقاء اللوم على المطور السابق، لكن الحقيقة غالبًا ما تكون أكثر تعقيدًا. لا يمكننا رؤية المستقبل، لذلك من المستحيل أن نفهم كيف ستنمو المتطلبات أو التكنولوجيا أو أهداف العمل عندما نقوم بتصميم نظام شبكي جديد. ونتيجة لذلك، يمكن أن تصبح الأنظمة غير قابلة للقراءة مع زيادة نطاقها جنبًا إلى جنب مع اعتماد الشركة عليها. وهذا نوع من التناقض: فالأنظمة الأقدم والأكثر صعوبة في الصيانة غالبًا ما توفر القيمة الأكبر. من الصعب العمل عليهم لأنهم كبروا مع الشركة، ومن المخيف العمل عليهم لأن كسره قد يكون كارثة.
هذا هو ما أدعوكم إليه: إذا كنتم تحبون المشكلات الصعبة والمجزية... جربوها. خذ أقدم نظام لديك واجعله قابلاً للصيانة. أنت تعرف الشخص الذي أتحدث عنه - الشخص الذي لن "يمتلكه" أحد. هذا هو ما تعتمد عليه الأقسام الأخرى ولكن المهندسين يكرهونه. الذي كان عليك تصحيحه Log4Shell أولاً . افعلها. أتحداكم.
لقد أتيحت لي مؤخرًا فرصة لتحديث نظام التعلم الآلي الموجود منذ عقد من الزمن في Bazaarvoice. على السطح، لا يبدو الأمر مثيرًا : هذا الشيء لا يحتوي حتى على شبكات عصبية! من يهتم! حسنًا... كان الأمر مهمًا. يعالج هذا النظام تقريبًا كل مراجعة للمنتجات التي ينشئها المستخدمون وتتلقاها Bazaarvoice - ما يقرب من 9 ملايين شهريًا - ويفعل ذلك من خلال 90 مليون استدعاء استدلالي لنماذج التعلم الآلي. نعم - 90 مليون استدلالات! إنه نطاق ضخم، ولم أستطع الانتظار حتى أغوص فيه.
في هذا المنشور، سأشارك كيف أن تحديث هذا النظام القديم من خلال إعادة التصميم، بدلاً من إعادة الكتابة، سمح لنا بجعله قابلاً للتطوير وفعالاً من حيث التكلفة دون الاضطرار إلى محو كل التعليمات البرمجية والبدء من جديد. النظام الناتج هو بدون خادم، ومحتوي على حاوية، وقابل للصيانة مع تقليل تكاليف الاستضافة لدينا بنسبة 80٪ تقريبًا.
ما هو النظام القديم؟
يشير النظام القديم إلى برامج و/أو أجهزة الحوسبة القديمة التي تظل قيد التشغيل. وفي حين أنه لا يزال بإمكانه تحقيق غرضه الأصلي، إلا أنه يفتقر إلى قابلية التوسع للنمو المستقبلي.
الأنظمة القديمة القديمة
أولاً، دعونا نلقي نظرة على ما نتعامل معه هنا. كان النظام القديم الذي كان فريقي يقوم بتحديثه يشرف على المحتوى الذي ينشئه المستخدمون لجميع Bazaarvoice. وعلى وجه التحديد، فهو يحدد ما إذا كان كل جزء من المحتوى مناسبًا لمواقع الويب الخاصة بعملائنا.
يبدو هذا واضحًا - قم بإزالة المخالفات الواضحة مثل خطاب الكراهية أو اللغة البذيئة أو الإغراءات - ولكن في الممارسة العملية، فهو أكثر دقة. كل عميل لديه متطلبات فريدة لما يعتبره مناسبًا. العلامات التجارية للبيرة، على سبيل المثال، تتوقع مناقشات حول الكحول، ولكن العلامة التجارية للأطفال قد لا تتوقع ذلك. نحن نلتقط هذه الخيارات الخاصة بالعميل عندما نستقبل عملاء جدد، ويقوم فريق خدمة العملاء لدينا بتشفيرها في قاعدة بيانات الإدارة.
لمزيد من التعقيد، نقوم أيضًا بأخذ عينات من مجموعة فرعية من المحتوى الخاص بنا ليتم الإشراف عليها بواسطة المشرفين البشريين. يتيح لنا ذلك قياس أداء نماذجنا بشكل مستمر واكتشاف الفرص لبناء المزيد من النماذج.
تظهر البنية الكاملة لنظامنا القديم أدناه:
هذا النظام لديه بعض العيوب الخطيرة. على وجه التحديد - تتم استضافة جميع النماذج على مثيل EC2 واحد. لم يكن هذا بسبب سوء الهندسة، بل فقط عدم قدرة المبرمجين الأصليين على توقع الحجم الذي تريده الشركة. ولم يكن أحد يتصور أنها سوف تنمو بقدر ما فعلت.
بالإضافة إلى ذلك، عانى النظام من رفض المطورين: فقد تمت كتابته بلغة Scala، وهو ما لم يفهمه سوى عدد قليل من المهندسين. وبالتالي، غالبًا ما يتم تجاهله من أجل التحسين حيث لم يرغب أحد في لمسه.
ونتيجة لذلك، استمر النظام في النمو بطريقة تحافظ على الأضواء مضاءة. وبمجرد أن قمنا بإعادة تصميمه، كان يعمل على نسخة واحدة x1e.8xlarge. يحتوي هذا الشيء على ما يقرب من تيرابايت من ذاكرة الوصول العشوائي ويكلف تشغيله حوالي 5000 دولار شهريًا (غير محجوزة). لا تقلق، فقد أطلقنا للتو إصدارًا ثانيًا للتكرار وثالثًا لضمان الجودة.
كان تشغيل هذا النظام مكلفًا وكان معرضًا لخطر الفشل بشكل كبير (يمكن لنموذج واحد سيئ أن يؤدي إلى تعطيل الخدمة بأكملها). علاوة على ذلك، لم يتم تطوير قاعدة التعليمات البرمجية بشكل نشط وبالتالي كانت قديمة بشكل كبير مع حزم علوم البيانات الحديثة ولم تتبع ممارساتنا القياسية للخدمات المكتوبة في Scala.
نظام جديد
عند إعادة تصميم هذا النظام كان لدينا هدف واضح: جعله قابلاً للتطوير. كان تقليل تكاليف التشغيل هدفًا ثانويًا، كما كان الحال أيضًا مع تسهيل إدارة النماذج والتعليمات البرمجية.
التصميم الجديد الذي توصلنا إليه موضح أدناه:
كان النهج الذي اتبعناه لحل كل هذه المشكلات هو وضع كل نموذج للتعلم الآلي على نقطة نهاية معزولة بدون خادم SageMaker. كما هو الحال مع وظائف AWS Lambda، يتم إيقاف تشغيل نقاط النهاية بدون خادم عند عدم استخدامها - مما يوفر لنا تكاليف وقت التشغيل للنماذج قليلة الاستخدام. يمكنهم أيضًا التوسع بسرعة استجابةً للزيادات في حركة المرور.
بالإضافة إلى ذلك، قمنا بعرض خيارات العميل لخدمة صغيرة واحدة تقوم بتوجيه المحتوى إلى النماذج المناسبة. كان هذا هو الجزء الأكبر من التعليمات البرمجية الجديدة التي كان علينا كتابتها: واجهة برمجة تطبيقات صغيرة يسهل صيانتها وتسمح لعلماء البيانات لدينا بتحديث النماذج الجديدة ونشرها بسهولة أكبر.
هذا النهج له الفوائد التالية:
- تم تقليل الوقت اللازم للتقييم بما يزيد عن 6x. على وجه التحديد، يتم توجيه حركة المرور إلى النماذج الحالية بشكل فوري، ويمكن نشر النماذج الجديدة في أقل من 5 دقائق بدلاً من 30 دقيقة.
- التوسع بلا حدود – لدينا حاليًا 400 نموذج ولكننا نخطط لتوسيع نطاقها إلى الآلاف لمواصلة زيادة كمية المحتوى الذي يمكننا الإشراف عليه تلقائيًا
- شهدنا انخفاضًا في التكلفة بنسبة 82% عند الاستغناء عن EC2 حيث يتم إيقاف تشغيل الوظائف عند عدم استخدامها، ونحن لا ندفع مقابل الأجهزة عالية المستوى غير المستغلة بشكل كافٍ
ومع ذلك، فإن مجرد تصميم بنية مثالية ليس هو الجزء الصعب المثير للاهتمام حقًا في إعادة بناء النظام القديم، حيث يتعين عليك الانتقال إليه.
كان التحدي الأول الذي واجهنا في عملية الترحيل هو معرفة كيفية ترحيل نموذج Java WEKA لتشغيله على SageMaker، ناهيك عن SageMaker Serverless.
لحسن الحظ، ينشر SageMaker النماذج في حاويات Docker، لذلك يمكننا على الأقل تجميد إصدارات Java والإصدارات التابعة لتتناسب مع التعليمات البرمجية القديمة لدينا. وهذا من شأنه أن يساعد في ضمان أن النماذج المستضافة في النظام الجديد تُرجع نفس نتائج النموذج القديم.
لجعل الحاوية متوافقة مع SageMaker، كل ما عليك فعله هو تنفيذ بعض نقاط نهاية HTTP المحددة:
-
POST /invocation
— قبول الإدخال وإجراء الاستدلال وإرجاع النتائج. -
GET /ping
- يُرجع 200 إذا كان خادم JVM سليمًا
(لقد اخترنا تجاهل كل ما يتعلق بحاويات BYO متعددة النماذج ومجموعة أدوات الاستدلال SageMaker.)
بعض التجريدات السريعة حول com.sun.net.httpserver.HttpServer وكنا على استعداد للبدء.
وتعلم ماذا؟ كان هذا في الواقع ممتعًا جدًا. كان اللعب بحاويات Docker وإجبار شيء عمره 10 سنوات على SageMaker Serverless يحمل طابعًا ترقيعيًا. لقد كان الأمر مثيرًا للغاية عندما نجحنا في تشغيله - خاصةً عندما حصلنا على رمز النظام القديم لإنشائه في مكدس sbt الجديد الخاص بنا بدلاً من maven.
سهّلت حزمة sbt الجديدة العمل عليها، وضمنت عملية النقل بالحاويات حصولنا على السلوك المناسب أثناء التشغيل في بيئة SageMaker.
الهجرة إلى النظام الجديد
إذن لدينا النماذج في حاويات ويمكننا نشرها على SageMaker - لقد أوشكنا على الانتهاء، أليس كذلك؟ ليس تماما.
الدرس الصعب حول الترحيل إلى بنية جديدة هو أنه يجب عليك إنشاء ثلاثة أضعاف نظامك الفعلي فقط لدعم الترحيل. بالإضافة إلى النظام الجديد، كان علينا بناء:
- خط أنابيب لالتقاط البيانات في النظام القديم لتسجيل المدخلات والمخرجات من النموذج. استخدمنا هذه للتأكد من أن النظام الجديد سيعود بنفس النتائج
- خط أنابيب لمعالجة البيانات في النظام الجديد لحساب النتائج ومقارنتها بالبيانات الموجودة في النظام القديم. يتضمن هذا قدرًا كبيرًا من القياس باستخدام Datadog ويحتاج إلى توفير القدرة على إعادة تشغيل البيانات عندما نجد تناقضات
- نظام نشر كامل للنماذج لتجنب التأثير على مستخدمي النظام القديم (والذي سيؤدي ببساطة إلى تحميل النماذج إلى S3). كنا نعلم أننا نريد نقلها إلى واجهة برمجة التطبيقات (API) في نهاية المطاف، ولكن بالنسبة للإصدار الأولي، كنا بحاجة إلى القيام بذلك بسلاسة
كان كل هذا عبارة عن تعليمات برمجية سهلة الاستخدام، علمنا أنه يمكننا التخلص منها بمجرد الانتهاء من ترحيل جميع المستخدمين، ولكن لا يزال يتعين علينا بنائها والتأكد من تطابق مخرجات النظام الجديد مع النظام القديم.
توقع هذا مقدما.
على الرغم من أن إنشاء أدوات وأنظمة الترحيل استغرق بالتأكيد أكثر من 60% من وقتنا الهندسي في هذا المشروع، إلا أنه كان أيضًا تجربة ممتعة. أصبح اختبار الوحدة أشبه بتجارب علم البيانات: لقد كتبنا مجموعات كاملة للتأكد من أن مخرجاتنا متطابقة تمامًا . لقد كانت طريقة تفكير مختلفة جعلت العمل أكثر متعة. خطوة خارج صناديقنا العادية، إذا صح التعبير.
تحديث الأنظمة القديمة من خلال إعادة الهيكلة
في المرة القادمة التي تميل فيها إلى إعادة بناء نظام من التعليمات البرمجية، أود أن أشجعك على محاولة ترحيل البنية بدلاً من التعليمات البرمجية. ستجد تحديات تقنية مثيرة للاهتمام ومجزية، ومن المرجح أن تستمتع بها أكثر بكثير من مجرد تصحيح أخطاء الحالات غير المتوقعة للتعليمات البرمجية الجديدة الخاصة بك.
تريد معرفة المزيد؟ شاهد الحديث الذي ألقيته في AWS Data Summit أدناه، والذي يتعمق في الجانب المتعلق بـ MLOps من الأشياء.