Dubboサービスの優雅な停止
6024 ワード
サービスプロバイダが停止した場合、新しいリクエストを受信しないとマークし、新しいリクエストが来たときに直接エラーを報告し、クライアントに他のマシンを再試行させる.次に、スレッドプール内のスレッドが実行されているかどうかを検出し、タイムアウトしない限り、すべてのスレッドの実行が完了するまで待機します.サービス消費者が停止すると、新しい呼び出し要求は開始されず、すべての新しい呼び出しはクライアントでエラーが発生します.その後、リクエストの有無を検出した応答はまだ返されず、タイムアウトしない限り強制的に閉じられます.
ここではまずフックプログラムとは何かを説明します.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()エクスポートされたサービスを閉じる まとめ
オンラインサービスは簡単な
ここではまずフックプログラムとは何かを説明します.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秒です.(タイムアウトは強制的に閉じます)
サービス側フックプログラムを見てみましょう.
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 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(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(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(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))
を閉じる.閉じるときは、ポートとシステムリソースを解放するために、サービスを閉じる必要があります.オンラインサービスは簡単な
kill -9
ではなく、kill
トリガアプリケーションのフックプログラムを行い、関連するリソースのクリーンアップを行い、ずっと閉じられなければ、最終的にkill -9
を通じて実行することができます.