1

时间追溯到2018年12月的某一天夜晚,那天我正准备上线一个需求完就回家,刚点下发布按钮,告警就响起,我擦,难道回不了家了?看着报错量只有一两个,断定只是偶发,稳住不要慌。

把剩下的机器发完,又出现了几个同样的错误,作为一名优(咸)秀(鱼)程序员,这种问题必须追查到底。

2

娴熟地查询到报错日志

org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed

看着异常信息,陷入了沉思

  • 表面上看报错是因为使用了已经关闭的数据源

  • 数据源什么时候会关闭呢?只有进程被杀死的时候

  • 莫非是应用关闭时不够平滑?发布时会先摘除流量的呀,应该不至于呀

天色已经很晚,漫无目的地拖动日志,疲惫地寻找新线索,突然报错日志中一个单词引入眼帘:「rocketmq」

精神抖擞,大概知道原因了,这应用中还有个兢兢业业的rocketmq consumer一直在消费消息,在应用关闭时,外部流量被摘除了,但没人通知rocketmq consumer,于是它抛异常了。

3

出于我对rocketmq不深刻甚至有点肤浅的理解,它的消费采用ack的方式,如果报错,消息稍后还会重试,不会丢消息,而且如果消费代码是幂等的,也不会有业务上的异常,总之这不重要,因为它也不是我写的代码。

瞅了一眼consumer的代码(这里就不贴代码了,反正贴了你也不会看),consumer注册了一个ShutdownHook,ShutdownHook里consumer执行了shutdown来优雅地退出,并且给这个shutdownThread设置了最高优先级,然而从实践看来,这个线程最高优先级并没有什么卵用。

而且从《ShutdownHook原理》这篇文章中也知道ShutdownHook是并发执行的,spring容器关闭也是一个ShutdownHook,他们之前没有先后顺序。

了解原因后,第一时间想到了类似dubbo摘流的方案,吭哧吭哧写了个优雅关闭rocketmq cosnumer的接口,在应用关闭脚本的kill之前调用该接口,完美解决问题,赶紧下班回家,不然要猝死了。

4

夜里入睡,梦到老板让我把所有的系统都改造掉,吓得我一机灵。

于是第二天又重新思考这个问题,总觉得在应用里实现一个接口并在stop脚本中去调用是一件非常不优雅的事,更重要的是这也没法复制到其他项目,我又陷入了沉思。

既然是spring容器关闭时bean的销毁顺序导致的问题,那么能不能利用spring的depend-on把顺序理顺了?说干就干。

起初我遇到是这样的依赖关系:

手把手在xml的每个bean中把depend-on关系都配上,似乎也起到了作用。

但当我打开第二个项目时,它的bean之间的依赖关系大致如下:

好家伙,26个字母差点不够用,当时我的心情是这样的

所以我觉得以当前的速度,改造完所有项目可能都到9102年了。

5

又过了一段时间,在github交友网站上突然看到了rocketmq官方实现的spring-boot-starter,于是点进去看了它的实现。好家伙,看完直呼666。

官方starter实现了spring的SmartLifecycle接口,它的start方法能在所有bean初始化完成后被调用,stop方法会在bean被销毁前调用,对rocketmq consumer来说简直完美。

顺便还复习了一下spring容器的关闭,代码在AbstractApplicationContext的doClose方法,这里我总结成一幅图:

通过上图能看到,销毁bean之前,有关闭lifecycle bean和发送ContextClosedEvent两个动作,官方starter选择了实现LifeCycle接口的方式。

6

到这里我该给老板汇报去了,之所以rocketmq consumer发布时不平滑是我们的使用姿势问题,虽然对业务没影响,但不优雅,解决方案有两个,老板你选吧:

  • 全都换成官方starter,依赖spring-boot,官方维护,改造成本很高,

  • 监听ContextClosedEvent来实现优雅关闭,这块可以封装一下,让业务方引入依赖即可

推荐:

主流Java进阶技术(学习资料分享)

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

RocketMQ 优雅停机技巧相关推荐

  1. 不懂优雅停机,搞挂了线上服务该咋办?

    作者丨陈树义 来源丨公众号:陈树义(ID:gh_b6f5025d4a8d) 公司项目是用 consul 进行注册的,在发布微服务的时候,总是会导致调用方出现一定几率的调用失败.一开始百思不得其解,后来 ...

  2. 不懂优雅停机,搞挂了线上服务,咋办?

    公司项目是用 consul 进行注册的,在发布微服务的时候,总是会导致调用方出现一定几率的调用失败.一开始百思不得其解,后来咨询了资深的同事才知道:原来是服务下线的时候没有优雅停机,没有去 consu ...

  3. Spring Boot 2.3.0 新特性:优雅停机!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 前言:关于Spring Boot.Spring Cloud应用的优 ...

  4. SpringBoot 2.3 新特性之优雅停机,这波操作太秀了!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 什么是优雅停机 先来一段简单的代码,如下: @RestContro ...

  5. springboot 优雅停机_Spring Boot 2.3 新特性优雅停机详解

    什么是优雅停机 先来一段简单的代码,如下: @RestControllerpublic class DemoController { @GetMapping("/demo") pu ...

  6. 聊聊Spring Boot中的优雅停机

    大家好,我是推干货的DD! 今早在社区(spring4all.com)看到一个不错的问题: 感兴趣的小伙伴可以先自己思考一下,或者看一下源码. 关于优雅停机,网上的文章讲的比较透的不多,好多都是复制黏 ...

  7. Spring Boot 2.3.0 新特性:优雅停机

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 前言:关于Spring Boot.Spring Clou ...

  8. 一文聊透 Dubbo 优雅停机

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | kiritomoe 来源 | 公众号「Kirito的技术分享」 1 前言 一年之前 ...

  9. 研究优雅停机时的一点思考

    作者:徐靖峰 来源:Kirito的技术分享 开头先废话几句,有段时间没有更新博客了,除了公司项目比较忙之外,还有个原因就是开始思考如何更好地写作. 远的来说,我从大一便开始在 CSDN 上写博客,回头 ...

  10. shutdown thread.java_ShutdownHook- Java 优雅停机解决方案

    想象一下,如果你现在刚好在 word 上写需求文档,电脑突然重启.等待开机完成,你可能会发现写了一个小时文档没有保存,就这么没了... 一个正在运行 Java 应用如果突然将其停止,影响不止数据丢失, ...

最新文章

  1. [杭电ACM]3336Count the string
  2. BRCM5.02编译十:cmake: command not found
  3. C++ 暂停Windows文件保护
  4. git 冲突覆盖_git pull冲突解决之强制覆盖
  5. linux 磁盘管理3板斧,Linux 磁盘管理的命令
  6. Hadoop精华问答 | 关于Hadoop核心技术的精华问答
  7. css 文本溢出 0302
  8. 嵌入式开发笔记(二)嵌入式系统启动过程 (S5pv210)
  9. 一致性Hash简单介绍和使用
  10. promise的链式调用
  11. kali2020.3 安装IDA freeware
  12. vue实现简单的日历
  13. 去伪、存真、打破、重塑……网贷业暴雷潮之下的敬畏与回归
  14. python合并多个excel
  15. 微博分享代码怎么显示自定义来源
  16. USB-PPI数据电缆驱动
  17. Linux编程经典实例,PyQt4 精彩实例分析 - 实例1 Hello Kitty! _Linux编程_Linux公社-Linux系统门户网站...
  18. 软件设计实战:基于Java的俄罗斯方块游戏【完整版】
  19. D. Berserk And Fireball(模拟)
  20. [HTML5-SVG]SVG是什么?SVG有什么用途?

热门文章

  1. 使用bat命令快速创建系统还原点的方法
  2. Excel 2010 SQL应用066 返回数字与文本混杂的数据
  3. Vue报错:contains both .browserslistrc and package.json with browsers
  4. centos oracle 修改监听服务名_虚拟机(Oracle Virtual Box)下ORACLE的安装
  5. Linux操作系统———李纳斯
  6. Iphone版同步推闪退问题
  7. 为 Form Library 开发工作流,如何读取 InfoPath 表单内容
  8. 技术管理实战笔记-团队建设篇
  9. 如何删除计算机新用户,如何将电脑里的账户信息彻底删除
  10. 使用代理服务器网速会变慢吗?