
Di sini saya akan berbicara tentang perangkat salah satu dari banyak alat yang membantu dalam pengembangan berbagai layanan untuk proyek Odnoklassniki. Di dalam perusahaan, kami menyebutnya "Hot Code Replace" (HCR), dan alat ini dirancang untuk memperbaiki bug yang kritis dan tidak rumit dalam menjalankan layanan produksi tanpa menghentikannya. Ini adalah fitur yang sangat penting, karena ini memungkinkan Anda untuk menghindari proses yang agak membosankan dan menghabiskan waktu dalam menyusun versi baru dari layanan sampah, untuk menghindari kehadiran jeda yang cukup lama dalam ketersediaan setiap host, dan untuk menghindari pembilasan cache.
Secara umum, ini menghemat banyak waktu dan mengurangi interval sejak kesalahan terdeteksi hingga koreksi dari jam ke menit. Paling sering, seperti yang direncanakan, kesalahan kecil dalam kode diperbaiki, misalnya, programmer lupa untuk memeriksa nol dan untuk beberapa pengguna tindakan tertentu di situs mengarah ke kesalahan. Yaitu, ketika koreksi dilakukan dengan mengubah beberapa baris dalam metode. Dan demi perubahan kecil seperti itu, Anda tidak perlu lagi mengganggu kolega Anda dan menunggu berjam-jam untuk produksi.
Sebagai contoh:

Anda dapat dengan mudah memperbaikinya pada:

Tentu saja, Anda dapat membuat lebih banyak perubahan, pada saat yang sama menambahkan kelas baru, dengan cepat membuat perubahan yang diminta manajer pada saat yang sama, tanpa menunggu pembaruan berikutnya. Tapi ini sudah, jika Monsieur tahu banyak tentang penyimpangan.
Lebih lanjut, adalah mungkin untuk menempatkan "tambalan" satu sama lain dan hingga tak terbatas.
Tetapi alat ini tidak mahakuasa dan didasarkan pada fungsi standar yang ditawarkan oleh kelas Java:
java.lang.instrument.Instrumentation dan metodenya batal redefineClasses (definisi ClassDefinition ...) .
Instrumentation.redefineClasses menggantikan kelas yang sebelumnya dimuat dengan kode byte baru. Anda dapat membebani beberapa kelas dengan dependensi berbeda secara bersamaan. Overloading tidak mengubah instance kelas yang ada, tidak mengubah inheritance, dan tidak menyentuh bidang instance atau kelas. Anda hanya dapat mengubah tubuh metode, kumpulan konstanta dan atribut. Anda dapat menambahkan kelas atau subclass baru. Tanda tangan metode, bidang contoh, dan bidang kelas tidak dapat diubah. Jika Anda mencoba membuat perubahan yang tidak kompatibel, redefineClasses pada prinsipnya tidak akan berfungsi dan akan menimbulkan kesalahan. Harus diingat bahwa ketika kelas overload, eksekusi bagian kode overload tidak terganggu, bytecode baru akan digunakan saat metode yang sama dipanggil. Dan karena itu, jika Anda mencoba untuk memperbaiki kode metode yang memiliki siklus yang sangat panjang di dalamnya, maka penggantian yang sebenarnya akan terjadi hanya setelah siklus ini berakhir.
Jika cukup sederhana: Anda dapat mengubah kode hanya di dalam metode dan intinya.
Dan di sini adalah contoh loop sementara, yang sampai metode selesai, tidak akan diperbaiki.

Kesulitan utama adalah membuat alat yang bekerja di ekosistem Odnoklassniki, alat yang cocok dengan semua proses kerja yang ada. Yang akan secara konsisten dan transparan berinteraksi dengan semua layanan di ratusan host, serta menjadi fleksibel dan mudah digunakan. Alat ini harus mengatasi lusinan percobaan, pekerjaan, dan pembaruan yang terus-menerus terjadi pada produksi.
Bagaimana proses menginstal tambalan terlihat seperti dari pengembang / admin mencoba untuk memperbaiki bug pada produksi, tetapi sehingga dapat dilakukan menggunakan beberapa prosedur standar dan dapat diandalkan pada lusinan server. Kami menghilangkan proses menemukan dan memperbaiki kesalahan dalam kode.
1. Brunch terpisah dibuat di GIT untuk perbaikan kode. Menggunakan versi sangat penting bukan hanya karena kenyamanan, tetapi juga untuk penyelidikan selanjutnya.
2. TeamCity meluncurkan proses pembuatan patch. Pertama, perakitan proyek dibuat dari brunch yang ditentukan, dan kemudian perakitan baru dibandingkan dengan yang dipasang pada produksi. Untuk melakukan ini, saya menulis plug-in untuk alat build, yang mengekstrak semua file dari arsip, membandingkan perbedaan dan memilih hanya file-file yang telah diubah atau ditambahkan. Dalam hal ini, versi Java compiler di kedua majelis harus sama, karena versi lain dari kompiler akan membuat file yang berbeda dan hampir semua file proyek akan dimasukkan dalam tambalan. Sangat penting untuk membuat arsip kecil saja, di mana hanya file yang diperlukan saja yang akan didapat Ini secara signifikan akan mempercepat proses pengiriman tambalan ke puluhan server. Proses pembangunan tidak hanya cocok untuk tambalan kode proyek, tetapi Anda juga dapat mengganti pustaka yang ditambal dalam proyek. Ketika membandingkan konten dari dua majelis, perbedaan akan ditemukan di perpustakaan (file jar).
3. Jika perakitan berhasil, tambalan dikirim ke repositori khusus, dan di jendela hasil dikeluarkan kunci (atau hash), yang diperlukan untuk mengidentifikasi tambalan secara unik dan beberapa jaminan bahwa kode ini akan sampai ke produksi.

Nah, dan lagi - Anda dapat menambal jumlah yang tidak terbatas kali dan membangun dengan nomor versi yang sama akan berbeda dengan hash.
4. Selanjutnya, semua aktivitas ditransfer ke layanan konfigurasi, di mana di UI biasa Anda dapat menentukan untuk layanan mana, di mana host dan versi aplikasi yang Anda perlu tambal.

Banyaknya parameter memberikan tingkat fleksibilitas pengaturan yang diperlukan, yang sangat penting di kebun binatang besar dari banyak server. Katakanlah pada beberapa bagian server nomor versi aplikasi berbeda, dan Anda tidak perlu menambal kode ini sama sekali. Atau, untuk verifikasi, Hot Code Rreplace pertama kali diluncurkan pada satu server, atau pada sekelompok server, dan kemudian didistribusikan di semua instance aplikasi.
5. Melalui perubahan konfigurasi, layanan yang dipilih menerima informasi tentang apa yang perlu dipasang patch, versi dan hash verifikasi. Idenya adalah bahwa semua layanan menerima perintah "instal patch" dan kemudian bertindak secara independen. Mereka secara independen membandingkan versi mereka sendiri dan hanya jika versi cocok dan hash dari tambalan hilang atau berbeda, mereka secara mandiri mengunduh rakitan tambalan dari repositori. Proses unduhan itu sendiri terjadi melalui HTTP, dan Anda dapat dengan cepat mengubah alamat repositori, jumlah upaya unduhan dan masa tunggu antar percobaan.
6. Setiap aplikasi secara lokal memeriksa hash rakitan dan membukanya. Pada saat yang sama, setiap file diperiksa untuk keberadaannya dalam array di antara yang dikembalikan oleh Instrumentation.getAllLoadedClasses (), semua kelas dan file baru ditulis ke yang baru - classpath sementara, dan classpath ini ditambahkan melalui Instrumentation.appendToSystemClassLoaderSearch (), dan kelas yang ada dibaca ke dalam memori dan melewati metode redefineClasses.
7. Seluruh proses: kedatangan sinyal tentang perlunya menambal aplikasi, pengunduhan, verifikasi, pembongkaran dan aplikasi dicatat secara rinci, baik dalam log umum dengan aplikasi dan sendiri, sehingga Anda dapat dengan cepat dan tanpa gerakan yang tidak perlu memantau proses.
8. Setelah tambalan berhasil diterapkan, proses berakhir dengan mengubah versi aplikasi menjadi tambalan dengan menambahkan baris yang dibuat khusus termasuk patch hash. Jika untuk beberapa host versi tidak berubah ke yang diharapkan, kita pergi ke log Hot Code Replace untuk host itu dan melihat apa yang terjadi di sana. Jika ini adalah masalah komunikasi, maka Anda dapat dengan aman mengulangi perintah tambalan dan host yang diinginkan akan mencoba lagi.
Apa masalah yang mungkin dapat mencegah aplikasi dari patch? Ada beberapa dari mereka, dan di antara mereka fungsi dari kelas Instrumentasi saya akan menempatkan di tempat terakhir. Hingga saat ini, kode bengkok yang tidak memenuhi persyaratan ketat redefineClasses selalu di-flash oleh JVM tanpa konsekuensi apa pun untuk aplikasi tersebut. Saat menerapkan metode redefineClasses, JVM sepenuhnya menghentikan aplikasi, tetapi proses ini membutuhkan waktu sepersekian detik. Karena sama sekali tidak menakutkan.
Momen paling berisiko adalah pengiriman tambalan ke server, yang diputuskan oleh pelatihan ulang tambahan. Tetapi jika penelusuran ulang tidak membantu, maka Anda dapat mengulangi perintah untuk memanggil tambalan dan masing-masing host akan mencoba mengulangi prosesnya, tetapi instal tambalan hanya jika perlu, mis. tambalan belum diinstal sebelumnya atau jika kunci hash telah berubah.
Masalah potensial lainnya adalah ketika perbaikan tersebut memperbaiki satu kesalahan dan menambahkan yang baru. Untuk meminimalkan risiko ini, pertama-tama kami unggah tambalan ke sejumlah server, lihat log, bagan, dan pantau hasilnya. Dan baru setelah itu kami meluncurkan koreksi ke host lain.
Apa yang harus dilakukan dengan memulai ulang aplikasi atau server? Ini sudah tertanam dalam logika semua aplikasi teman sekelas: salah satu yang pertama dalam aplikasi apa pun adalah modul HCR. Dan jika selama inisialisasi informasi tentang perlunya patch aplikasi diperhatikan, patch akan diterapkan terlebih dahulu.
Dan sekarang sedikit tentang apa terdiri dari Hot Code Replace.
- JavaAgent kami. JavaAgent, jika ada yang lupa , ini adalah arsip * .jar yang terpisah dan dibentuk secara khusus yang diambil oleh JVM ketika aplikasi mulai menggunakan parameter tambahan, misalnya: -javaagent: /path/to/lib/my-agent.jar Berkat fitur tambahan Javaagent- dan dimungkinkan untuk menggunakan sihir pengganti kode. Di agen itulah kelas java.lang.instrument.Instrumentation tersedia. Tapi, saya tidak menyumbat dia (agen) dengan kode tambahan, karena Pembaruan agen adalah tugas yang tidak sepele, tetapi cukup memindahkan instance dari kelas Instrumentasi ke bidang statis dari kelas utilitas. Dengan demikian, semua manipulasi dapat dimulai dari mana saja di aplikasi.
- Layanan konfigurasi - bertanggung jawab atas konfigurasi salah satu aplikasi kami dan oleh karena itu diinisialisasi dalam setiap aplikasi terlebih dahulu. Di sanalah fungsi utama Hot Code Replace disembunyikan. Pada startup aplikasi atau ketika mengubah konfigurasi HCR untuk aplikasi tertentu, kompatibilitas versi diperiksa dan semua manipulasi di atas dilakukan.
- TeamCity dan membangun skrip - untuk dengan mudah membuat "tambalan" dan hanya menyimpan kelas dan sumber daya yang dimodifikasi atau ditambahkan di dalamnya.
Apa kelebihan yang kita miliki dari alat ini? Yang pertama adalah kecepatan memperbaiki kesalahan kritis pada prod. Dari log, saya melihat bahwa rekan kerja secara bertahap mulai menggunakan HCR semakin sering, alih-alih menunggu rilis. Berikutnya adalah kecepatan aplikasi. Aplikasi tidak perlu dihentikan, JVM hanya membeku selama sepersekian detik dan semua benda Anda tetap di tempatnya masing-masing dan terus bekerja.
Dan pengembang kami sembuh secara bebas dan bahagia dan memperbaiki kesalahan mereka dengan segera dan secara mandiri langsung dalam produksi tanpa memperhatikan jumlah server dan beban.