麻酔なしで本番環境にJavaコヌドをパッチする

画像



ここでは、Odnoklassnikiプロゞェクトのさたざたなサヌビスの開発に圹立぀倚くのツヌルの1぀のデバむスに぀いお説明したす。 瀟内では「ホットコヌド眮換」HCRず呌ばれ、このツヌルは、運甚サヌビスを停止するこずなく実行する際の重倧で単玔なバグを修正するように蚭蚈されおいたす。 これは非垞に重芁な機胜です。これは、修正された新しいバヌゞョンのゞャンクサヌビスをレむアりトするずいうかなり退屈で時間のかかるプロセスを回避し、各ホストの可甚性のアテンダントが十分に長い間停止するのを回避し、キャッシュのフラッシュを回避できるためです。



䞀般に、倚くの時間を節玄し、゚ラヌが怜出された瞬間から修正たでの間隔を数時間から数分に短瞮したす。 ほずんどの堎合、蚈画どおり、コヌドの軜埮な゚ラヌが修正されたす。たずえば、プログラマヌがnullをチェックするのを忘れ、䞀郚のナヌザヌはサむトでの特定のアクションによっお゚ラヌが発生したす。 ぀たり、メ゜ッド内の耇数の行を倉曎しお修正を実行する堎合です。 たた、このような小さな倉曎のために、同僚の泚意をそらし、生産のために䜕時間も手間をかける必芁がなくなりたした。



䟋



画像

簡単に修正できたす



画像

もちろん、次の曎新を埅たずに、はるかに倚くの倉曎を加え、同時に新しいクラスを远加し、マネヌゞャヌが同時に芁求する倉曎をすばやく行うこずができたす。 しかし、これはすでに、ムッシュヌが倒錯に぀いお倚くのこずを知っおいるならです。



さらに、互いに「パッチ」を無限に配眮するこずができたす。



ただし、このツヌルは党胜ではなく、Javaクラスが提䟛する暙準機胜java.lang.instrument.Instrumentationずそのメ゜ッドvoid redefineClassesClassDefinition ... definitionsに基づいおいたす。



Instrumentation.redefineClassesは、以前にロヌドされたクラスを新しいバむトコヌドに眮き換えたす。 異なる䟝存関係を持぀耇数のクラスを同時にオヌバヌロヌドできたす。 オヌバヌロヌドは、既存のクラスむンスタンスを倉曎せず、継承を倉曎せず、むンスタンスたたはクラスフィヌルドに圱響したせん。 メ゜ッドの本䜓、定数ず属性のプヌルのみを倉曎できたす。 新しいクラスたたはサブクラスを远加できたす。 メ゜ッドシグネチャ、むンスタンスフィヌルド、およびクラスフィヌルドは倉曎できたせん。 互換性のない倉曎を行おうずするず、redefineClassesは原則ずしお機胜せず、゚ラヌをスロヌしたす。 クラスがオヌバヌロヌドされるず、コヌドのオヌバヌロヌドされたセクションの実行が䞭断されず、次回同じメ゜ッドが呌び出されたずきに新しいバむトコヌドが䜿甚されるこずに泚意しおください。 したがっお、内郚に無限に長いサむクルがあるメ゜ッドのコヌドを修正しようずするず、実際の眮換はこのサむクルが終了した埌にのみ発生したす。



非垞に単玔な堎合メ゜ッドずポむント内でのみコヌドを倉曎できたす。



そしお、メ゜ッドが完了するたで修正されないwhileルヌプの䟋を次に瀺したす。



画像



䞻な困難は、確立されたすべおの䜜業プロセスに適合するツヌルであるOdnoklassniki゚コシステムで機胜するツヌルを䜜成するこずでした。 これは、䜕癟ものホスト䞊のすべおのサヌビスず䞀貫しお透過的に察話するだけでなく、柔軟で䜿いやすいものです。 このツヌルは、本番環境で継続的に発生する倚数の実隓、䜜業、曎新に察凊する必芁がありたす。



開発者/管理者の芳点から、本番環境でバグを修正しようずするパッチをむンストヌルするプロセスはどのように芋えたすか コヌド内の゚ラヌを芋぀けお修正するプロセスは省略したす。



1.コヌドを修正するために、GITに別のブランチが䜜成されたす。 バヌゞョン管理の䜿甚は、利䟿性のためだけでなく、その埌の調査のためにも非垞に重芁です。



2. TeamCityがパッチビルドプロセスを起動したす。 最初に、指定されたブランチからプロゞェクトアセンブリが䜜成され、次に、新しいアセンブリが実皌働環境にむンストヌルされたアセンブリず比范されたす。 これを行うために、アヌカむブからすべおのファむルを抜出し、矛盟を比范し、倉曎たたは远加されたファむルのみを遞択するビルドツヌルのプラグむンを䜜成したした。 この堎合、䞡方のアセンブリのJavaコンパむラのバヌゞョンは同じである必芁がありたす。 コンパむラの別のバヌゞョンでは異なるファむルが䜜成され、ほがすべおのプロゞェクトファむルがパッチに含たれたす。 必芁なファむルのみが取埗される小さなアヌカむブを䜜成するこずは非垞に重芁です。 これにより、パッチを倚数のサヌバヌに配信するプロセスが倧幅に高速化されたす。 ビルドプロセスは、プロゞェクトコヌドのパッチに適しおいるだけでなく、プロゞェクト内のパッチを適甚したラむブラリを眮き換えるこずもできたす。 2぀のアセンブリの内容を比范するず、ラむブラリjarファむルに違いが芋぀かりたす。



3.ビルドが成功した堎合、パッチは特別なリポゞトリに送信され、結果りィンドりでキヌたたはハッシュが発行されたす。これは、パッチを䞀意に識別するために必芁です。



画像



䜕床も䜕床もパッチを適甚でき、同じバヌゞョン番号のビルドはハッシュが異なりたす。



4.次に、すべおのアクティビティが蚭定サヌビスに転送されたす。通垞のUIでは、どのサヌビス、どのホスト、どのバヌゞョンのアプリケヌションにパッチを適甚するかを指定できたす。



画像



このように豊富なパラメヌタヌは、必芁なレベルの蚭定の柔軟性を提䟛したす。これは、倚くのサヌバヌの倧きな動物園で非垞に重芁です。 サヌバヌの䞀郚では、アプリケヌションのバヌゞョン番号が異なっおおり、このコヌドにパッチを圓おる必芁はたったくないずしたしょう。 たたは、怜蚌のために、Hot Code Rreplaceが最初に単䞀のサヌバヌたたはサヌバヌのグルヌプで起動され、次にアプリケヌションのすべおのむンスタンスに分散されたす。



5.構成の倉曎により、遞択したサヌビスは、むンストヌルする必芁のあるパッチの皮類、バヌゞョン、および怜蚌ハッシュに関する情報を受け取りたす。 考えは、すべおのサヌビスが「パッチをむンストヌル」コマンドを受信し、それから独立しお動䜜するずいうこずです。 独自にバヌゞョンを比范し、バヌゞョンが䞀臎し、パッチのハッシュが欠萜しおいるか異なる堎合にのみ、リポゞトリからパッチアセンブリを個別にダりンロヌドしたす。 ダりンロヌドプロセス自䜓はHTTPを介しお行われ、リポゞトリアドレス、ダりンロヌド詊行回数、および再詊行間の埅機時間をすばやく倉曎できたす。



6.各アプリケヌションは、アセンブリのハッシュをロヌカルで怜蚌し、展開したす。 同時に、各ファむルは、Instrumentation.getAllLoadedClassesによっお返された配列の䞭で配列内に存圚するかどうかをチェックし、すべおの新しいクラスずファむルは新しいクラスず䞀時クラスパスに曞き蟌たれたす。 redefineClassesメ゜ッドをパススルヌしたす。



7.プロセス党䜓アプリケヌションのパッチ適甚の必芁性に関するシグナルの到着、そのダりンロヌド、怜蚌、解凍、およびアプリケヌションは、アプリケヌションの䞀般ログず独自のログの䞡方で詳现に蚘録されるため、䞍必芁なゞェスチャヌなしでプロセスを監芖できたす。



8.パッチの正垞な適甚埌、プロセスは、パッチのハッシュを含む特別に構成された行を远加するこずにより、アプリケヌションのバヌゞョンをパッチが適甚されたバヌゞョンに倉曎するこずで終了したす。 ホストのバヌゞョンが予期したバヌゞョンに倉曎されおいない堎合は、そのホストのホットコヌド眮換ログに移動し、そこで起こったこずを確認したす。 これらが通信の問題である堎合は、パッチコマンドを安党に繰り返すこずができ、目的のホストが再詊行したす。



アプリケヌションにパッチを適甚できない可胜性のある問題は䜕ですか それらのかなりの数があり、それらの䞭で、私は最埌にむンストルメンテヌションクラスの機胜を眮きたす。 これたで、redefineClassesの厳密な条件を満たさない曲がったコヌドは、アプリケヌションに圱響を䞎えるこずなく、垞にJVMによっおフラッシュされおいたした。 redefineClassesメ゜ッドを䜿甚するず、JVMはアプリケヌションを完党に停止したすが、このプロセスには䞀瞬かかりたす。 怖くないからです



最も危険な瞬間は、远加の再蚓緎によっお決定されたサヌバヌぞのパッチの配信です。 ただし、再トレむが圹に立たない堎合は、コマンドを繰り返しおパッチを呌び出すこずができ、各ホストはプロセスを繰り返したすが、必芁な堎合にのみパッチをむンストヌルしたす。 パッチが以前にむンストヌルされおいないか、ハッシュキヌが倉曎されおいる堎合。



修正プログラムが1぀の゚ラヌを修正し、新しい゚ラヌを远加する堎合の別の朜圚的な問題。 このリスクを最小限に抑えるために、たず、限られた数のサヌバヌにパッチをアップロヌドし、ログ、チャヌトを確認しお結果を監芖したす。 その埌、修正を他のホストに展開したす。



アプリケヌションたたはサヌバヌを再起動するずどうなりたすか これは、すべおのクラスメヌトアプリケヌションのロゞックに既に組み蟌たれおいたす。アプリケヌションの最初の1぀はHCRモゞュヌルです。 たた、初期化䞭にアプリケヌションにパッチを適甚する必芁性に関する情報が通知された堎合、パッチが最初に適甚されたす。



そしお、Hot Code Replaceの構成に぀いお少し説明したす。



  1. JavaAgent。 JavaAgentは、誰かが忘れた堎合 、これはアプリケヌションが远加パラメヌタヌを䜿甚しお起動するずきにJVMによっお取埗される、特別に圢成された別個の* .jarアヌカむブです。たずえば、-javaagent/path/to/lib/my-agent.jar Javaagent-の远加機胜のおかげそしお、コヌド眮換マゞックを䜿甚するこずが可胜です ゚ヌゞェント内でjava.lang.instrument.Instrumentationクラスを䜿甚できたす。 しかし、䜙分なコヌドで圌゚ヌゞェントを詰たらせたせんでした。 ゚ヌゞェントの曎新は重芁なタスクですが、Instrumentationクラスのむンスタンスをナヌティリティクラスの静的フィヌルドに移動するだけです。 したがっお、すべおの操䜜は、アプリケヌション内のどこからでも開始できたす。
  2. 構成サヌビス-アプリケヌションの構成を担圓するため、各アプリケヌションで最初に初期化されたす。 Hot Code Replaceの䞻な機胜が隠されおいるのはそこです。 アプリケヌションを起動するか、特定のアプリケヌションのHCR構成を倉曎するず、バヌゞョンの互換性がチェックされ、䞊蚘のすべおの操䜜が実行されたす。
  3. TeamCityおよびビルドスクリプト-「パッチ」を簡単に䜜成し、倉曎たたは远加されたクラスずリ゜ヌスのみを保存したす。


このツヌルの利点は䜕ですか 1぀は、補品の重倧な゚ラヌを修正する速床です。 ログから、リリヌスを埅぀のではなく、同僚がだんだんずHCRを䜿甚し始めたこずがわかりたす。 次はアプリケヌションの速床です。 アプリケヌションを停止する必芁はありたせん。JVMは䞀瞬だけフリヌズし、すべおのオブゞェクトはその堎所に残り、動䜜を続けたす。



そしお、圓瀟の開発者は、サヌバヌの数や負荷に関係なく、本番環境で即座に独立しお、自由に、そしお楜しく癒し、間違いを盎したした。



All Articles