[apache/dubbo]Spring Boot 优雅停机失效,报 ExtensionDirector is destroyed

2024-06-24 25 views
2
Environment
  • Dubbo version: 3.1.0
  • Java version: 1.8.0
  1. 在 Spring Boot 环境下启动 Dubbo Provider 应用
  2. 启动 Dubbo Consumer 并发持续调用 Provider 应用
  3. kill 该进程

像文档说的那样可以优雅停机

实际情况是会报一大堆异常,并将异常返回至 Consumer 端。异常内容大多是:

[ERROR][2022-09-18 15:52:05.826][tri-protocol-20881-thread-200][org.apache.dubbo.rpc.filter.ExceptionFilter]  [DUBBO] Got unchecked and undeclared exception which called by 172.17.0.221. service: cn.jojo.api.service.bs.ms.IMediaService, method: getEditMediaResult, exception: java.lang.IllegalStateException: ExtensionDirector is destroyed, dubbo version: 3.1.0, current host: 172.17.0.28
问题根因

Dubbo 的优雅停机实际上有两种机制:

  1. Spring Boot 环境下 DubboDeployApplicationListener#onContextClosedEvent 监听到 ContextClosedEvent 时执行停机。
  2. DubboShutdownHook 监听 JVM 的 shutdownHook

这两种机制同时运行时,会导致相互冲突,上边提到的报错ExtensionDirector is destroyed就是因为 DubboShutdownHook 关闭了 ExtensionDirector 导致的。

解决办法

在经过反复测试后,只保留 DubboDeployApplicationListener 事件监听机制,是可以实现优雅停机的,而 DubboShutdownHook 的停机实际上并不优雅,它只是停机而已,甚至用不到 dubbo.service.shutdown.wait 参数,这个参数是通过 DubboDeployApplicationListener 监听事件最后走到 RegistryProtocol 中实现的。

建议在 Spring Boot 环境下默认关闭注册 DubboShutdownHook

另一个问题

DubboShutdownHook 提供了参数 dubbo.shutdownHook.listenIgnore 来阻止注册 JVM shutdownHook,但是这个参数是在类构造器中初始化的,而这个类的构造器又调用太早,导致读不到配置中心的配置,连 Spring Boot 配置也读不到,只有添加启动参数 -Ddubbo.shutdownHook.listenIgnore=true 才行。

而添加启动参数在规模稍大一些的系统中,是很难做到的,大家都是用配置中心来统一管理配置。

回答

8

这一块可以做成在 DubboDeployApplicationListener 成功注册的时候对应的 module 不再受 DubboShutdownHook 管控,同时 DubboShutdownHook 完善整体等待机制,特别是对于有 Spring 绑定的 module 可以进行等待,超过一段时间仍未退出后再执行统一关闭。

1

可以帮忙提个 PR 完善这一块

5

我也遇到了同样的问题,问下你这边是怎么解决的?测试过程中发现DubboShutdownHook好像会注册两次,既然参数 dubbo.shutdownHook.listenIgnore 不能在配置中读取到,那在什么地方去取消注册DubboShutdownHook呢?

6

能否细说下你是怎么重现该bug的?为什么我按照作者的重现步骤做好多次都是能正常停机,并没有作者反馈的ExtensionDirector is destroyed bug信息?我猜想是不是还有什么相关的配置才能重现。

另外看源码中,虽然Dubbo 的优雅停机会有两种机制同时运行,但是通过原子变量+CAS控制了,当两者同时停止某一项时,只会有一种机制执行。所以难以理解怎么出现该bug的。

7

@JihanChen 加启动参数-Ddubbo.shutdownHook.listenIgnore=true

0

@pandaapo 试试开启 triple 协议或 dubbo + triple 双协议