Dubbo: Elegant downtime

1. Overview

Dubbo accomplishes elegant downtime through JDK's HutdownHook, so if a user uses a mandatory shutdown command such as kill-9 PID, the elegant downtime will not be executed and will only be executed through kill PID.

From the location of the code, this is not a good location.However, this is an appropriate location considering that it is guaranteed to be initialized to ShutdownHook.Of course, from the official TODO, there may be a change of place in the future.

Line 7: Call the Abstract Registry Factory#destroyAll() method, destroy all Registries, and unsubscribe and register service providers and consumers in the application.For a detailed analysis, see 「2.1 AbstractRegistryFactory」 Medium.

Lines 9 to 15: sleep waits for a period of time for service consumers in other applications to receive a registry notification that the service provider for the application is offline, increasing the success rate of elegant downtime without retrying.

Of course, this is not an absolute wait, but rather the developer configures the "dubbo.service.shutdown.wait" parameter to set the wait time in milliseconds.ConfigUtils#getServerShutdownTimeout() method with the following code:

Whether you use the most version 2.5.3 or the latest version 2.5.7, you can't do elegant downtime without setting up a retry mechanism. This change is mainly to modify a little code and add a configurable wait time to simply do "graceful downtime without starting a retry".

The main implementation mechanism is to add a configurable wait time in the two phases, [after provider s disconnect the registry, before closing the response], and [after consumer s remove invoker s, before closing the client]. Currently, hands-on testing can be done without configuring retries or with elegant downtime.

Since most dubbo-enabled companies now turn off retry mechanisms to avoid extreme avalanches and traffic storms, most interfaces fail to do elegant downtime with the current Dubbo elegant downtime settings, so the elegance without retrying is enhanced here in a simpler waySuccess rate of downtime.

Lines 17 to 28: Destroy all Protocol s.There are two types of protocols currently layered:

Protocol implementation classes for specific protocols, such as dubbo:// corresponding DubboProtocol, hessian:// corresponding HessianProtocol, focus on service exposure and reference.Because DubboProtocol is the most commonly used, we take it for example in 「2.2 DubboProtocol」 Share in.

In fact, an application can be both a service provider and a service consumer.Therefore, you need to close ExchangeClient and ExchangeServer.

Lines 4 to 17: Loop the HeaderExchangeServer#close(timeout) method to destroy all ExchangeServers.For a detailed analysis, see 「2.2.1 HeaderExchangeServer」 .

Lines 19 to 32: Loop the ReferenceCountExchangeClient#close(timeout) method to destroy all ReferenceCountExchangeClients.Inside the method, the HeaderExchangeClient#close(timeout) method is called to close the HeaderExchangeClient object.For a detailed analysis, see 「2.2.2 HeaderExchangeClient」.

Lines 3 to 16: Cycle to destroy all Invokers (DubboInvoker here) of service consumers corresponding to the agreement (DubboProtocol).For a detailed analysis, see 「2.2.3 DubboInvoker」 .

Lines 17 to 30: Cycle, destroy all Exporters (DubboExporter here) of the service provider corresponding to the agreement (DubboProtocol).For a detailed analysis, see 「2.2.4 DubboExporter」 .

2.2.1 HeaderExchangeServer

#close(timeout) method, the overall process is as follows:

The red box section: Because the ProtocolListenerWrapper and the ProtocolFilterWrapper and Protocols'Ubbo SPI Wrapper implementation classes, they are called first when the DubboProtocol#destroy() method is called.At present, it is just a layer of packaging, no logic, the code is as follows:

Calling the #invoke(Invocation) method after the tag has been destroyed throws an RpcException exception.The code is as follows:

@Override
public Result invoke(Invocation inv) throws RpcException {
if (destroyed.get()) {
throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost()
+ " use dubbo version " + Version.getVersion()
+ " is DESTROYED, can not be invoked any more!");
}
// ...omit other code
}

x

Lines 20 to 27: Loop, call the ReferenceCountExchangeClient#close(timeout) method, and close the client.In fact, the client has been closed in the DubboProtocol#destroy() method.Although it looks duplicated, it doesn't.Because DubboInvoker needs to be destroyed when the remote service provider closes, the client's link must be closed.Therefore, DubboInvoker must have this logic.

Because the service provider integrates the Configurator of configuration rules, you need to use ExporterChangeableWrapper to save the original Invoker object.

Therefore, all of the above DE-exposure logic cannot destroy the ExporterChangeableWrapper's mapping to bounds and needs to be implemented through the #destroy() method of RegistryProtocol s.

Therefore, the exposed Exporter object, exporter, is called here and has been DE-exposed by the AbstractExporter#unexport() method.However, this logic cannot be removed here, because there may be a place to call the ExporterChangeableWrapper#unexport() method.

3. ExecutorUtil

3.1 gracefulShutdown

The #gracefulShutdown(executor, timeout) method closes gracefully, prohibits new tasks from being submitted, and completes old tasks.

But the reality is very complex, if you rely on consumer to answer and confirm.So Dubbo's choice is:

Provider removes itself from registry.And sleep waits for a certain amount of time (developer-allocated) for consumer to be notified.Of course, this process is not absolutely successful.For example, consumer cannot connect to registry, but to the upper provider.

provider informs consumer that he is ready to close and does not ask for himself.When all notifications are complete, wait until the original request is processed.When finished, close the local server and thread pool.

Of course, consumer also gracefully shuts down, waiting for all the requests it makes to end.Relatively simple.