ترقيع كود جافا عند الإنتاج بدون تخدير

الصورة

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

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

على سبيل المثال:

الصورة
يمكنك إصلاحه بسهولة على:

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

علاوة على ذلك ، من الممكن وضع "بقع" على بعضها البعض وإلى ما لا نهاية.

لكن هذه الأداة ليست كلية الوجود وتستند إلى الوظائف القياسية التي توفرها فئة Java: java.lang.instrument.Instrumentation وأسلوبها باطل redefineClasses (ClassDefinition ... تعريفات) .

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

إذا بكل بساطة: يمكنك تغيير الرمز فقط داخل الأساليب والنقطة.

وهنا مثال على حلقة while ، والتي لن يتم إصلاحها حتى اكتمال الطريقة.

الصورة

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

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

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

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

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

الصورة

حسنًا ، ومرة ​​أخرى - يمكنك تصحيح عدد غير محدود من المرات ، وستختلف الإصدارات بنفس رقم الإصدار باختلاف التجزئة.

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

الصورة

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

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

6. يتحقق كل تطبيق محليًا من تجزئة التجميع ويفككه. في هذه الحالة ، يتم التحقق من وجود كل ملف في الصفيف من بين تلك التي تم إرجاعها بواسطة Instrumentation.getAllLoadedClasses () ، تتم كتابة جميع الفئات والملفات الجديدة إلى فئة جديدة - مسار مؤقت مؤقت ، وتتم إضافة مسار الصف هذا من خلال Instrumentation.appendToSystemClassLoaderSearch () ، وتتم قراءة الفئات الموجودة في الذاكرة و تمر من خلال طريقة redefineClasses.

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

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

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

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

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

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

والآن قليلاً عن ما يتكون منه Hot Code Replace.

  1. JavaAgent لدينا. JavaAgent ، إذا نسي أي شخص ، هذا هو أرشيف * .jar منفصل ، تم تشكيله خصيصًا والذي يتم التقاطه بواسطة JVM عندما يبدأ التطبيق باستخدام معلمة إضافية ، على سبيل المثال: -javaagent: /path/to/lib/my-agent.jar بفضل الميزات الإضافية لـ Javaagent- ومن الممكن استخدام سحر استبدال الرمز. في الوكيل ، تتوفر فئة java.lang.instrument.Instrumentation. ولكن ، لم أسد له (الوكيل) برمز إضافي ، لأن تحديث الوكيل هو مهمة غير تافهة ، ولكن ببساطة نقل مثيل فئة Instrumentation إلى الحقل الثابت لفئة الأداة المساعدة. وبالتالي ، يمكن البدء في جميع التلاعبات من أي مكان في التطبيق.
  2. خدمة التهيئة - هي المسؤولة عن تهيئة أي من تطبيقاتنا ، وبالتالي تتم تهيئتها في كل تطبيق أولاً. هناك يتم إخفاء الوظيفة الرئيسية لاستبدال الرمز الساخن. عند بدء تشغيل التطبيق أو عند تغيير تكوين HCR لتطبيق معين ، يتم التحقق من توافق الإصدار ويتم تنفيذ جميع المعالجات المذكورة أعلاه.
  3. TeamCity وبناء البرامج النصية - لإنشاء "تصحيحات" بشكل ملائم وحفظ الفئات والموارد المعدلة أو المضافة فقط فيها.

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

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

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


All Articles