php etcd rpc,RPC实现原理之核心技术-优雅启动与关闭

如何实现优雅关闭

大家可能存有疑问,RPC 里面有服务注册与发现功能, 注册中心的作用就是用来管理服务的状态, 当服务关闭时, 会先通知注册中心进行下线, 然后通过注册中心移除节点信息,这样不就可以保障服务不被调用吗?

那我们来看下关闭的流程:

16e9927b3411960e966b2410aa1b0ae7.png

整个关闭过程中依赖了两次 RPC 调用,一次是服务提供方通知注册中心下线操作,一次是注册中心通知服务调用方下线节点操作。并且注册中心通知服务调用方都是异步的,并不能保证完全实时性,通过服务发现并不能做到应用的无损关闭。

有没有好的解决方案呢?

服务提供方已经进入关闭流程,那么很多对象已经被销毁了,这个时候我们可以设置一个请求“挡板”,挡板的作用就是告诉调用方,服务提供方已经开始进入关闭流程了,不能再处理其他请求了。

这就好比我们去超市结账,在交接班或者下班的时候, 收银员会放一个提示牌在柜台, 提示“该通道已关闭”,不能进行结账, 这个时候客户只能转移到其他可用的柜台上进行结账。

处理流程:

当服务提供方正在关闭,如果还收到了新的业务请求,服务提供方直接返回一个特定的异常给调用方。这个异常就是告诉调用方“我正在关闭,不能处理这个请求”,然后调用方收到这个异常响应后,RPC 框架把这个节点从健康列表挪出,并把其他请求自动重试到其他节点,因为这个请求是没有被服务提供方处理过,所以可以安全地重试到其他节点,这样就可以实现对业务几乎无损的处理。如果要更为完善, 我们还可以加上主动通知机制,这样既可以保证实时性,也可以避免客户端出现重试情况。

如何捕获关闭事件呢?

操作系统的进程的关闭,如果不是强制结束,进程会接收到一个结束信号,Java应用程序,在接收到结束信号时, 会调用Runtime.addShutdownHook 方法触发关闭钩子。 我们在 RPC服务启动的时候,提前注册关闭钩子,在里面添加处理程序,先开启挡板, 然后通知调用方服务已下线。当接收到新来的请求时,挡板会进行拦截,抛出特定异常。为了尽可能地完成正在处理的请求, 我们可以加入计数器机制,把剩余请求纳入计数器当中, 每处理完一个请求, 就减少一个计数, 将所有剩余请求处理完成之后, 再真正结束服务。

9258066f572f08a1bebef40f59be76c6.png

在Dubbo框架中, 在以下场景中会触发优雅关闭:

JVM主动关闭(System.exit(int);

JVM由于资源问题退出(OOM);

应用程序接受到进程正常结束信号:SIGTERM或SIGINT信号。

优雅停机是默认开启的,停机等待时间为10秒。可以通过配置dubbo.service.shutdown.wait来修改等待时间。

基于ShutdownHook方式的优雅停机无法确保所有关闭流程一定执行完成,所以 Dubbo 推出了多段关闭的方式来保证服务完全无损。在关闭应用前,首先通过 QOS(在线运维命令) 的offline指令下线所有服务,然后等待一定时间确保已经到达请求全部处理完毕,由于服务已经在注册中心下线,当前应用不会有新的请求。这时再执行真正的关闭(SIGTERM 或SIGINT)流程,就能保证服务无损。

Dubbo优雅关闭的源码:

DubboShutdownHook.register方法

注册关闭钩子: /**

* 注册关闭钩子,在服务关闭时触发执行

*/

public void register() {

if (!registered.get() && registered.compareAndSet(false, true)) {

Runtime.getRuntime().addShutdownHook(getDubboShutdownHook());

}

}

DubboShutdownHook.doDestroy方法

销毁所有相关资源: /**

* 关闭注销所有资源, 包括注册器和协议处理器。

*/

public void doDestroy() {

if (!destroyed.compareAndSet(false, true)) {

return;

}

// 销毁所有注册器,包括Zookeeper、etcd、Consul等等。

AbstractRegistryFactory.destroyAll();

// 销毁所有协议处理器,包括Dubbo、Hessian、Http、Jsong等。

destroyProtocols();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值