dubbo優雅停止
23221 ワード
サービスプロバイダが停止した場合、新しいリクエストを受信しないとマークし、新しいリクエストが来たときに直接エラーを報告し、クライアントに他のマシンを再試行させる.次に、スレッドプール内のスレッドが実行されているかどうかを検出し、タイムアウトしない限り、すべてのスレッドの実行が完了するまで待機します.サービス消費者が停止すると、新しい呼び出し要求は開始されず、すべての新しい呼び出しはクライアントでエラーが発生します.その後、リクエストの有無を検出した応答はまだ返されず、タイムアウトしない限り強制的に閉じられます.
ここではまずフックプログラムとは何かを説明します.Javaプログラムでは、閉じるフックを追加することで、プログラムが終了したときにリソースを閉じ、スムーズに終了する機能を実現することができます.Runtimeを使う.addShutdownHook(Thread hook)メソッドでは、JVMが閉じたフックを登録できます.このフックは、以下のシーンで呼び出すことができます.プログラム正常終了 はSystemを用いる.exit() 端末は、Ctrl+Cを使用するトリガされた割り込み を使用する.システムは を閉じる Kill pidコマンドを使用してプロセス を終了
私たちは
最終的には
最後に、
振り返ってdubboを見ると、優雅なダウンタイムのタイムアウト時間を設定できます.デフォルトのタイムアウト時間は10秒です.(タイムアウトは強制的に閉じます)
サービス側フックプログラムを見てみましょう.
その結果、
すべての serverは、サービス側が reference client共有リンクを閉じ、ReferenceCountExchangeClient ghost client(公式注釈では幽霊client)を閉じるこの操作は、プログラムバグがclientを誤って閉じることを防止するための防御措置 にすぎない.クリアstubメソッドMap suer.destroyはInvokerを閉じ、サービスを利用できないように設定します.そしてExporterを通ります.Uniexport()エクスポートされたサービスを閉じる 作者:jerrik
リンク:https://www.jianshu.com/p/6e4d1ecb0815
出典:簡書
著作権は作者の所有である.商業転載は著者に連絡して許可を得てください.非商業転載は出典を明記してください.
ここではまずフックプログラムとは何かを説明します.Javaプログラムでは、閉じるフックを追加することで、プログラムが終了したときにリソースを閉じ、スムーズに終了する機能を実現することができます.Runtimeを使う.addShutdownHook(Thread hook)メソッドでは、JVMが閉じたフックを登録できます.このフックは、以下のシーンで呼び出すことができます.
私たちは
Runtime.getRuntime().addShutdownHook()
を通じてフックを登録して、ApplicationShutdownHooks.add(hook)
に呼び出されて、最後にHOOKS
というIdentityHashMapに保存されていることを発見しました.それはいつフックプログラムをトリガーしたのですか.ApplicationShutdownHooks
には静的ブロックがありました static {
try {
Shutdown.add(1 /* shutdown hook invocation order */, false /* not registered if shutdown in progress */, new Runnable() { public void run() { runHooks(); } } ); hooks = new IdentityHashMap<>(); } catch (IllegalStateException e) { hooks = null; } }
最終的には
runHooks
メソッドが呼び出されます.System.exit()
を確認しますが、最終的にはShutDown.exit()->sequence()
を通じて入ってきて、runHooks
を呼び出してフックプログラムを呼び出します.Javaはどのようにkill
命令に応答したのでしょうか.SignalHandler
によって実現され、openjdkのwindowsディレクトリとsolarisディレクトリの下にTerminator.java
というコードがあります. SignalHandler sh = new SignalHandler() { public void handle(Signal sig) { Shutdown.exit(sig.getNumber() + 0200); } }; Signal.handle(new Signal("HUP"), sh); Signal.handle(new Signal("INT"), sh); Signal.handle(new Signal("TERM"), sh);
最後に、
void* oldHandler = os::signal(sig, newHandler)
によってlinuxシステムのsignal信号が取得される.振り返ってdubboを見ると、優雅なダウンタイムのタイムアウト時間を設定できます.デフォルトのタイムアウト時間は10秒です.(タイムアウトは強制的に閉じます)
<dubbo:application ...> <dubbo:parameter key="shutdown.timeout" value="60000" /> dubbo:application>
サービス側フックプログラムを見てみましょう.
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { if (logger.isInfoEnabled()) { logger.info("Run shutdown hook now."); } ProtocolConfig.destroyAll(); } }, "DubboShutdownHook"));
その結果、
ProtocolConfig.destroyAll()
メソッドが呼び出されました. public static void destroyAll() { AbstractRegistryFactory.destroyAll(); ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); for (String protocolName : loader.getLoadedExtensions()) { try { Protocol protocol = loader.getLoadedExtension(protocolName); if (protocol != null) { protocol.destroy(); } } catch (Throwable t) { logger.warn(t.getMessage(), t); } } }
すべての
Protocol
プロトコルをロードし、destroy
メソッドをループして呼び出します.次に、DubboProtocol
のdestroy
メソッドを見てみましょう. public void destroy() { for (String key : new ArrayList<String>(serverMap.keySet())) { ExchangeServer server = serverMap.remove(key); if (server != null) { try { if (logger.isInfoEnabled()) { logger.info("Close dubbo server: " + server.getLocalAddress()); } server.close(getServerShutdownTimeout()); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } for (String key : new ArrayList<String>(referenceClientMap.keySet())) { ExchangeClient client = referenceClientMap.remove(key); if (client != null) { try { if (logger.isInfoEnabled()) { logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); } client.close(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } for (String key : new ArrayList<String>(ghostClientMap.keySet())) { ExchangeClient client = ghostClientMap.remove(key); if (client != null) { try { if (logger.isInfoEnabled()) { logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress()); } client.close(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } } stubServiceMethodsMap.clear(); super.destroy(); }
DubboProtocol
のopenServer
を介してNettyを介してサービスを開始するため、serverMap.put(key, createServer(url))
を閉じる.閉じるときは、ポートとシステムリソースを解放するために、サービスを閉じる必要があります.リンク:https://www.jianshu.com/p/6e4d1ecb0815
出典:簡書
著作権は作者の所有である.商業転載は著者に連絡して許可を得てください.非商業転載は出典を明記してください.