Dubboエレガントダウン

4486 ワード

背景
どのオンラインアプリケーションでも、サービス更新の導入中にクライアントが認識しないことをどのように保証するかは、開発者が解決しなければならない問題です.すなわち、アプリケーションの停止からリカバリサービスの再開までの段階では、正常なビジネスリクエストに影響を与えることはできません.理想的には、要求がない場合に更新を行うことが最も安全で信頼性が高いが、インターネットアプリケーションは可用性を保証しなければならないため、技術的な面でアプリケーション更新プロセスを最適化し、サービスが更新時に損なわれないことを保証する必要がある.
従来の解決策は、アプリケーションの更新プロセスを手動でトラフィックを抽出し、アプリケーションを停止し、更新して再起動する3つのステップに分けることで、手動操作によってクライアントが更新に対する感知がないことを実現することである.この方式は簡単で有効であるが、制限が多い:ゲートウェイのサポートを借りてトラフィックを取り出すだけでなく、アプリケーションを停止する前に手動で判断して、移動要求が処理済みであることを保証する必要がある.このような人工的な介入が必要な方式はメンテナンスの複雑さが高く,規模の小さい応用しか適用できず,大規模なシステムでは使用できない.
したがって、コンテナ/フレームレベルで何らかの自動化メカニズムを提供して、トラフィックを自動的に抽出し、処理が完了して到着する要求を確保すれば、ビジネスが更新の影響を受けないことを保証するだけでなく、アプリケーションを更新する際のメンテナンス効率を大幅に向上させることができる.
このメカニズムは優雅な停止であり、現在、Tomcat/Undertow/Dubboなどの容器/フレームワークが関連して実現されている.以下に、優雅なダウンタイムとは、アプリケーションを停止する際に実行されるアプリケーションの正常な停止を保証する一連の動作を指す.これらの操作には、既存のリクエストの実行完了を待つ、スレッドを閉じる、接続を閉じる、リソースを解放するなどが含まれます.優雅なダウンタイムは、非正常なシャットダウンプログラムがデータの異常や損失を引き起こす可能性があり、アプリケーションの異常などの問題を回避することができます.エレガントなダウンタイムは本質的にJVMがオフになる前に実行される追加の処理コードです.
適用シーン
  • JVMアクティブクローズ(System.exit(int);
  • JVMはリソースの問題で終了した(OOM).
  • アプリケーションは、SIGTERMまたはSIGINT信号を受信する.

  • 構成方法
    サービスの優雅な停止
    Dubboでは、エレガントなダウンタイムはデフォルトでオンであり、ダウンタイム待ち時間は10000ミリ秒である.待ち時間は、dubbo.service.shutdown.waitを構成することによって変更することができる.
    たとえば、待ち時間を20秒に設定すると、次の構成を追加できます.
    dubbo.service.shutdown.wait=20000
    

    容器の優雅な停止org.apache.dubbo.container.Mainという容器方式を用いてDubboを使用する場合、dubbo.shutdown.hooktrueとして配置することによって、エレガントなダウンタイムをオンにすることもできる.
    QOSで優雅に上下線ShutdownHook方式に基づく優雅なダウンタイムは、すべてのクローズプロセスが必ず実行されることを確保できないため、Dubboはサービスが完全に損なわれないことを保証するために、複数のクローズ方式を発売した.
    マルチセグメント・シャットダウンの適用を停止するには、スクリプトを自動化したり、手動で操作したりすることで、スクリプトの各フェーズが完了することを保証する複数のステップがあります.
    アプリケーションを閉じる前に、まずQOSのofflineを介してすべてのサービスをオフラインするように命令し、その後、一定時間待って要求がすべて処理されたことを確保し、サービスが登録センターでオフラインになったため、現在のアプリケーションには新しい要求はありません.このとき、本格的なクローズ(SIGTERMまたはSIGINT)プロセスを実行すると、サービスが損なわれないことが保証されます.
    QOSはtelnetまたはHTTPで使用できますが、具体的にはDubbo-QOSコマンドの使用説明を参照してください.
    プロセス
    Providerはダウンタイム命令を受信した後
  • 登録センターからすべてのサービスをログアウトします.
  • 構成センターから動的構成の傍受を解除する.
  • は、すべての接続されたクライアントに読み取り専用イベントを送信し、新しい要求の受信を停止する.
  • は、到着したリクエストを処理するためにしばらく待機し、リクエスト処理スレッドプールを閉じる.
  • すべてのクライアント接続を切断します.

  • Consumerはダウンタイム命令を受信した後
  • は、要求への新規アクセスを拒否し、呼び出し例外を直接返す.
  • は、現在送信されているリクエストの実行が完了するのを待機し、応答がタイムアウトした場合、接続を強制的に閉じる.

  • 容器方式でDubboを運転する場合、容器が終了する準備をする前に、一連の資源放出と清掃作業を行うことができる.
    例えばSpringContainerを使用する場合、DubboのShutdownHookスレッドはApplicationContextstopcloseの方法を実行し、Beanのライフサイクルが完全であることを保証します.
    実装の原理
  • クラスorg.apache.dubbo.config.AbstractConfigがロードされると、org.apache.dubbo.config.DubboShutdownHookを介してShutdownHookがJVMに登録される.
    /**
     * Register the ShutdownHook
     */
    public void register() {
        if (!registered.get() && registered.compareAndSet(false, true)) {
            Runtime.getRuntime().addShutdownHook(getDubboShutdownHook());
        }
    }
    
  • 各ShutdownHookは、JVMによって終了時にorg.apache.dubbo.config.DubboShutdownHookの実行がトリガーされる個別のスレッドである.
    /**
     * Destroy all the resources, including registries and protocols.
     */
    public void doDestroy() {
        if (!destroyed.compareAndSet(false, true)) {
            return;
        }
        // destroy all the registries
        AbstractRegistryFactory.destroyAll();
        // destroy all the protocols
        destroyProtocols();
    }
    
  • は、まずすべての登録センターを閉鎖します.このステップは、次のとおりです.
  • 登録センターから発行されたすべてのサービスをログアウトします.
  • 現在のアプリケーションのすべての依存サービスの購読をキャンセルします.
  • 登録センターとの接続を解除します.

  • は、Protocolのすべてのdestroy()を実行し、主に以下を含む.
  • は、InvokerおよびExporterのすべてを廃棄する.
  • サーバを閉じ、接続されているすべてのClientに現在のサーバ読み取り専用イベントを送信します.
  • 独占/共有Clientを閉じ、接続を切断し、タイムアウトと再試行タスクをキャンセルします.
  • は、関連するすべてのリソースを解放します.

  • の実行が完了し、JVMを閉じます.

  • 注意事項
  • SIGKILLを使用してアプリケーションを閉じると、優雅な停止は実行されません.
  • エレガントなダウンタイムは、すべての送信/到着要求の終了を待つことを保証しません.
  • によって構成されるエレガントなダウンタイム待ち時間timeoutは、すべてのステップ待ち時間の合計ではなく、各destroyが実行する最大時間である.たとえば、構成待ち時間が5秒の場合、サーバのシャットダウン、Clientのシャットダウンなどのステップはそれぞれ5秒待ちになります.

  •  
    原文:http://dubbo.apache.org/zh-cn/blog/dubbo-gracefully-shutdown.html