1. 程式人生 > >(十六)優雅停機

(十六)優雅停機

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^.