xxl-job优雅停止停止执行器即客户端tomcat的临时解决办法

  • 前言
  • 评测
  • 问题
    • ■ 描述
    • ■ 可能引发的另一个bug
    • ■ 任务
  • 解决
    • ■ 修改xxl-job-admin源码
    • ■ 手动调用job服务端下线接口(2选1)
    • ■ job客户端改造优雅停机(2选1)
  • 最后

如果着急,可以直接跳到解决方案,不忙可以唠嗑一下。

前言

我所了解的目前主流分布式job就是elastic-job、xxl-job和PowerJob。ejob太重,pjob开源太晚,xxljob评价又不错,中庸地选型了xxl-job。
本文提供xxl-job优雅停止停止执行器即客户端tomcat时没有及时剔除服务,不停报错500的临时解决办法。(最近较忙积累了一堆内容,没空写博客,由于github上有道友翻出了这个问题,我就先写一下这个内容,后续还有一篇关于xxl-job企微告警的内容)

评测

如果把它看做是个人行为的开源框架那确实是没话说——起立致敬,要是站在分布式job唯一解决方案的角度去看待它,我觉得是不够理想的。如果是单体项目qz就足够了,然而xxl-job在分布式的支持上,我认为还不够好,目前仍有非常多的瑕疵,远远没达到可以停止维护的程度。由于是个人项目,观察github上的情况,可以发现作者基本已经停止维护了,项目状态就是open-issue很多,解决问题的人很少,换成中间件的话,这种程度基本意味着项目要凉。

(题外话——这就是国内的情况,大多有能力的程序员把时间花在较为功利性的行为上,要么走面霸路专注于底层的吹牛逼,要么会用就行类尝遍所有的潮流框架级技术,鲜少有人会去为这类开源框架贡献一份力,做些脚踏实地的事,社区活跃只有提问,没有解决,也就造成作者的力不从心,开源项目也就处于停摆状态——没有什么大bug,凑合着也能用)

网上评测的都是营销号复制来复制去,我甚至怀疑他们连github都没登过,这也就造成一搜xxl-job,搜索结果——好东西,什么bug都没有,而真正商用的人,就跟藏宝贝一样,改造的内容不会开源出来,也不会提出问题。

问题

■ 描述

执行器重启也就是tomcat重启时,如果你直接杀死tomcat,xxl-job不会认为执行器下线的,会在一段时间内不停调用这台tomcat的执行器,并且调度失败,500报错,如果你配置了告警,那完蛋了,邮箱轰炸,钉钉轰炸,企微轰炸,被运维立马拖出去暴打。

后面发现xxl-job是提供执行器下线接口的

==> com.xxl.job.admin.controller.JobApiController
==> @RequestMapping("/{uri}")
==> } else if (“registryRemove”.equals(uri))

,并且在客户端,只要是优雅停机,客户端就会调用xxl-job-admin端的停机。但是,随即又发现服务端的停机仍然存在问题。

这是21年5月17日我在github上提出的issue,后面发现2020年8月20日有个类似的issue,就明白凉了凉了,要么重新选型,要么自己解决吧。

issue2422:https://github.com/xuxueli/xxl-job/issues/2422

类似issue

issue1917:https://github.com/xuxueli/xxl-job/issues/1917

v-2.3.0
目前是 客户端优雅停机时会调用destroy方法 方法里调用api api/registryRemove 通知调度中心
xxl-job-admin里的registryRemove方法只删除了xxl_job_registry表的内容 剔除服务仍需等待线程registryMonitorThread(BEAT_TIMEOUT = 30) 默认为30s执行才会真正剔除执行器,会导致大概0-30s的时间分流某执行器全是500报错
JobRegistryHelper里预留了freshGroupRegistryInfo方法,我将registryMonitorThread内容放入大大降低了报错,只会损失执行registryMonitorThread内容期间的调用,是否计划有更优雅的方法。
从某种程度来说既然调用api/registryRemove肯定意味着客观停机,应即时剔除服务,执行器上线延迟可以接受,执行器下线延迟不太接受。

■ 可能引发的另一个bug

如果你没配置告警无所谓这个报错,后续可能也会出现慢sql,类似这个issue

issue2415:https://github.com/xuxueli/xxl-job/issues/2415

我帮助了这个题主找到了慢sql的原因,并提供了解决方案。题主项目调度log非200即失败日志太多,就会产生慢sql(应该是告警方法的sql查询)。

难过的是——费力帮忙解决,连声道谢都没有,拜托,我们也是时薪近百的人,帮你解决没给钱就算了,说声谢谢是应该的吧,最后更是没有把引起问题的原因发出来供大家开源参考。鄙视一下认为理所应当的伸手党行为,这也是很多开源项目作者寒心的原因,人家没收你一分钱,你只会责骂项目有问题,却没有帮助作者让开源项目做得更好,所以即使xxl-job存在很多问题,我是不敢说一声不好,只能提出问题,我自己有解决的发一份供大家参考。

■ 任务

保证job客户端优雅停机时,执行器可以及时剔除服务,防止无效调度。

解决

我处理这个问题的心态是能解决就好,坐等官方方案(就目前来看,短期内不太可能解决),花太多时间的话宁可选型其它框架,哈哈,也是属于白嫖党,不愿花太多精力。

■ 修改xxl-job-admin源码

找到
com.xxl.job.admin.core.thread.JobRegistryHelper
拉到最下面,有这么一个方法

private void freshGroupRegistryInfo(RegistryParam registryParam){// Under consideration, prevent affecting core tables
}

翻译:正在考虑,防止影响核心表
说明作者也是有在考虑这个问题,但是还没实现预留了一个方法。

我给大家一个临时解决方案。

很简单,将61行处// for monitor ==》while (!toStop) { 里的部分内容复制过来即可。
即——

private void freshGroupRegistryInfo(RegistryParam registryParam){// Under consideration, prevent affecting core tablestry {// auto registry groupList<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().findByAddressType(0);if (groupList!=null && !groupList.isEmpty()) {// remove dead address (admin/executor)List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findDead(RegistryConfig.DEAD_TIMEOUT, new Date());if (ids!=null && ids.size()>0) {XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);}// fresh online address (admin/executor)HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT, new Date());if (list != null) {for (XxlJobRegistry item: list) {if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {String appname = item.getRegistryKey();List<String> registryList = appAddressMap.get(appname);if (registryList == null) {registryList = new ArrayList<String>();}if (!registryList.contains(item.getRegistryValue())) {registryList.add(item.getRegistryValue());}appAddressMap.put(appname, registryList);}}}// fresh group addressfor (XxlJobGroup group: groupList) {List<String> registryList = appAddressMap.get(group.getAppname());String addressListStr = null;if (registryList!=null && !registryList.isEmpty()) {Collections.sort(registryList);StringBuilder addressListSB = new StringBuilder();for (String item:registryList) {addressListSB.append(item).append(",");}addressListStr = addressListSB.toString();addressListStr = addressListStr.substring(0, addressListStr.length()-1);}group.setAddressList(addressListStr);group.setUpdateTime(new Date());XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);}}} catch (Exception e) {logger.error(">>>>>>>>>>> xxl-job, job registry remove thread error:{}", e);}}

■ 手动调用job服务端下线接口(2选1)

如果你是暴力关闭服务tomcat类似kill -9 类型,可以选择手动调用下线接口。
在关闭tomcat前调用该接口,过个几秒后再杀死服务的tomcat。

curl.exe -H "Content-Type:application/json"
-H "XXL-JOB-ACCESS-TOKEN:你的鉴权token"
-X POST --data
"{\"registryGroup\": \"EXECUTOR\",\"registryKey\": \"xxl-job-executor-zzdserver\",\"registryValue\": \"http://执行器ip:port/\"}"
http://服务端ip:port/api/registryRemove

■ job客户端改造优雅停机(2选1)

上面的做法当然是不推荐的,服务最好是优雅停机,我是选型actuator来优雅停机的(actuator内容这里不介绍,后续会写一篇jenkins的文章集成actuator),在优雅停机的时候,spring自然会调用执行器的销毁方法,销毁方法内包含上面那个接口的调用,内容也会更多,类似停止新调度,执行完旧调度最后关闭,不过作者写的现有内容好像有问题,好像是先杀再停止新调度,我在引入xxl-job的销毁后,shutdown接口无法很快关闭,基本上都是等到超时。

bat内容如下,sh其实类似,可供参考

rem ****** 重启前准备 ********
@echo offset "FILE_HOME=C:\Program Files\JenkinsFileA"rem 进入d盘d:D:\...\curl.exe -X POST http://服务ip:8085/actuator/shutdownrem 延迟20sping -n 20 1271  for /F "tokens=5" %%i in ( 'netstat -ano ^| findstr :8080' ) do taskkill /f /pid  %%i  /txcopy /e /y "%FILE_HOME%\config\*" "D:\...\A\config\" rem 复制jar到运行目录copy "%FILE_HOME%\***.jar" "D:\...\A\***.jar"schtasks /Run /TN "deploy-restart-a"echo good bye
@echo on

最后

这样重启我们自己的服务的时候,xxl-job就基本不会500报错,只是偶尔的报kill job,这也是漏洞,由于出现概率较低可以接受,所以我没有去解决。如果你有更好的方案,欢迎提供。

xxl-job优雅停止执行器即客户端tomcat相关推荐

  1. Spring Boot 优雅停止服务的几种方法

    作者 | 黄青石 来源 | https://www.cnblogs.com/huangqingshi/p/11370291.html 最近突然想到了优雅停止 SpringBoot 服务问题,在使用 S ...

  2. linux 优雅重启进程,apache2 重启、停止、优雅重启、优雅停止

    停止或者重新启动apache有两种发送信号的方法 第一种方法: 直接使用linux的kill命令向运行中的进程发送信号.你也许你会注意到你的系统里运行着很多httpd进程.但你不应该直接对它们中的任何 ...

  3. python 程序停止打印日志_优雅停止 SpringBoot 服务,拒绝 kill -9 暴力停止!

    在使用 SpringBoot 的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭.而且一些没有执行完的程序就会直接 ...

  4. springboot 优雅停机_SpringBoot 优雅停止服务的几种方法 第309篇

    相关历史文章(阅读本文之前,您可能需要先看下之前的系列?) 国内最全的Spring Boot系列之三 一分钟get:缓存穿透.缓存击穿.缓存雪崩 - 第304篇 布隆过滤器Bloom Filter竟然 ...

  5. Springboot实战:Springboot+Netty优雅的创建websocket客户端 (附源码下载)

    Springboot-cli 开发脚手架系列 Netty系列:Springboot+Netty优雅的创建websocket客户端 (附源码下载) 文章目录 Springboot-cli 开发脚手架系列 ...

  6. Kubernetes 优雅停止 Pod,Pod停止前处理设定任务的最佳方式

    何谓优雅停止? 优雅停止(Graceful shutdown)这个说法来自于操作系统,我们执行关机之后都得 OS 先完成一些清理操作,而与之相对的就是硬中止(Hard shutdown),比如拔电源. ...

  7. controller调用controller的方法_SpringBoot 优雅停止服务的几种方法

    转自:博客园,作者:黄青石 www.cnblogs.com/huangqingshi/p/11370291.html 在使用 SpringBoot 的时候,都要涉及到服务的停止和启动,当我们停止服务的 ...

  8. springboot 优雅关闭_Springboot 优雅停止服务的几种方法

    在使用Springboot的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭.而且一些没有执行完的程序就会直接退出 ...

  9. SpringBoot 优雅停止服务的几种方法

    方法一 Springboot提供的actuator的功能,它可以执行shutdown, health, info <dependency><groupId>org.spring ...

最新文章

  1. ArchiCAD 23中文版
  2. SpringMVC运行报错 unable to find resource 'XXX.vm' in any resource loader
  3. HDU 3487 Play with Chain | Splay
  4. 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m
  5. [css] 举例说明CSS特性检测的方式有哪些?
  6. Python笔记-BeautifulSoup中find_all的使用及str中trim()
  7. matlab动力学仿真_机械系统动力学MATLAB仿真(上)
  8. github 搜索_github 项目搜索技巧让你更高效精准地搜索项目
  9. hexo之Volantis主题美化
  10. 2022美赛M奖经验总结(3)选题思路篇
  11. 720s ideapad 黑苹果_Hackintosh 黑苹果长期维护机型 EFI 及安装教程整理
  12. ico在线制作,网站小图标Favicion.ico在线制作工具软件
  13. 数据分析 - 安然事件
  14. 买卖股票的最佳时机 II Java (贪心算法)
  15. Simotion应用与组网之一安装篇
  16. Clickhouse:日志表占用大量磁盘空间怎么办?
  17. 低噪声与功放选型购买
  18. 凝心聚力共赢未来!“数智新基建,低碳新发展”港股开户活动圆满落
  19. 和ZLTT一起学pwn 2.ret2text
  20. 基于matlab的多径信道的仿真

热门文章

  1. 李兴华java8教程_李兴华Java培训系列详解20套视频教程下载
  2. 【计算机网络面试】tcp/ip协议三次握手、四次挥手
  3. 金山词霸的词库读取程序
  4. C++酒店点菜管理系统[2022-12-31]
  5. Cisco路由器配置GRE隧道
  6. HPE还将继续支持下一代Superdome GPU芯片
  7. 项目管理相关认证简要介绍(2)- PMP
  8. 【FPGA-DSP】第九期:音频信号处理
  9. glade java_Gtk+/Glade编程(一)--简介
  10. (附源码)计算机毕业设计ssm超市会员积分管理系统