dubbo的优雅停机,借助于java虚拟机的关闭钩子来实现。
打开关闭钩子需要配置dubbo启动参数dubbo.shutdown.hook为true,才会使用关闭钩子启用优雅停机。
在钩子里,调用dubbo的容器(有spring,log4j,jetty等容器,即com.alibaba.dubbo.container.Container的实现类)的stop方法,释放相关资源。
spring在关闭时,会调用bean的destroy方法,dubbo的bean是扩展spring的,dubbo的bean会实现spring的接口DisposableBean的destroy方法:
不管是service,还是reference,都会将停机标记destroyed属性设为true
service:
public void destroy() {
if (isDestroyed()) {
return;
}
destroyed = true;
setAvailable(false);
}
reference:
public synchronized void destroy() {
if (ref == null) {
return;
}
if (destroyed){
return;
}
destroyed = true;
try {
invoker.destroy();
} catch (Throwable t) {
logger.warn("Unexpected err when destroy invoker of ReferenceConfig(" + url + ").", t);
}
invoker = null;
ref = null;
}
dubbo在调用服务时,会判断服务是否已经销毁,用一个destroyed标记来标明,下面源码:
com.alibaba.dubbo.rpc.protocol.AbstractInvoker<T>
public Result invoke(Invocation inv) throws RpcException {
if(destroyed) {
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!");
}
//other source code...
}
如果服务已经停用了,会抛出异常,客户端会根据配的集群策略调用其他的服务。
停机时:
客户端不再发起新的调用请求,新的调用请求都会报错,如果还有请求未返回结果,会等待一段时间(停机超时时间),超时则强制停机;
服务端不会接收新的请求,检查线程池是否还有任务未完成,有则等待一段时间(停机超时时间),超时则强制停机。
停机超时时间,dubbo默认是10秒,也可以配置指定超时时间:
# dubbo.properties
dubbo.service.shutdown.wait=10000
除了使用ShutdownHook,还可以通过调用:ProtocolConfig.destroyAll();
自己写了个RPC:
可以给个star,^0^.