关于XXLJOB集群模式下调度失败的问题
xxljob在集群模式下调度高频任务时,有时会出现调度失败的问题,具体报错如下:
java.io.EOFException: HttpConnectionOverHTTP@6be8bf0c(l:/10.48.2.64:38538 <-> r:/10.48.1.125:18989,closed=false)[HttpChannelOverHTTP@296ee40c(exchange=HttpExchange@4d219770 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@3c6b8ccf(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator{s=START}],recv=HttpReceiverOverHTTP@12554491(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of -1}]]]
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.earlyEOF(HttpReceiverOverHTTP.java:277)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1305)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.shutdown(HttpReceiverOverHTTP.java:182)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:129)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:69)
at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:90)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:174)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:748)
网上关于这个问题的原因和解决比较少,因此记录下来问题的排查过程,供大家参考,如果有心急的同学可以直接跳到结尾查看问题原因和解决方案
后续说明中的触发侧是指xxljob的服务端,执行侧是指任务执行的应用端
排查过程中需要对xxljob的执行原理有大概的了解,以及tcp的握手和挥手操作有一定的了解,最后还需要知道一些tcpdump命令结果的一些知识,如果有不明白的可以先查一下相关资料
首先,我看到这个问题之后先去网上搜一下有没有问题的原因说明和解决方案,但是查询之后发现虽然很多人都遇到了,但是没有说明具体的问题原因
所以,只好查看一下xxl的源码,发现触发操作是完全隔离的,集群下不同机器没有任何相互影响。而且非集群模式下没有这个问题,说明可以排除网络因素。
同时,我也将xxljob中发起触发请求的代码复制出来,然后进行高频率调用,但是没有复现出问题,说明问题的出现可能跟高频执行没有太大关系
肯定是不同机器调度过程中导致的,仔细观察下图中的调度记录,可以看到出问题的时间点总是在切换调度机器的第一次请求时发生。但是调度机器触发操作是完全独立的,所以到这里就不明白为什么会出现这种情况
于是,为了进一步排查问题,只能去尝试抓一下网络请求,看网络请求有什么不同

下面这个图是通过tcpdump命令抓取的任务触发机器和任务执行机器的网络通信过程
看到这个我才发现,虽然xxljob是使用http进行通信的,但是并不是走的短连接,而是长连接。
所以第一时间我认为是可能不同机器都已经建立了长连接但是由于调度触发一直在其中一台机器上,所以另一台的连接可能已经断开了,当触发切换到另一台机器时,由于连接已经断开,但是应用层尚未感知到,所以造成的问题
另外,从这个网络交互日志中可以看到复用长连接的有效时间是30s(这个其实是后面发现问题的关键)

根据上面分析的结果,思考问题的其他表现时,发现上面的推断并不能解释所有的现象,比如下图的表现

如果长连接已经中断,那么触发侧的请求无法发送到执行侧,执行侧的信息也无法反馈到触发侧才对。但是上面这个图中可以明显看到触发侧已经获取到了执行侧的报错信息,说明,执行侧报错之后已经通过原有连接将报错信息返回到了触发侧
这说明问题发生时,连接并没有中断,上面的分析是错误的。
之后又抓取到了问题发生时的网络交互日志,其中10.48.2.64.38538是xxljob服务端,也就是触发侧,10.48.1.125.18989是任务执行应用,也就是执行侧
16:26:46.008470 IP 10.48.2.64.38538 > 10.48.1.125.18989: Flags [P.], seq 756:1511, ack 344, win 219, length 755
16:26:46.009007 IP 10.48.1.125.18989 > 10.48.2.64.38538: Flags [F.], seq 344, ack 756, win 56, length 0
16:26:46.009192 IP 10.48.2.64.38538 > 10.48.1.125.18989: Flags [F.], seq 1511, ack 345, win 219, length 0
16:26:46.009916 IP 10.48.1.125.18989 > 10.48.2.64.38538: Flags [.], ack 1512, win 59, length 0
从上面这个日志中可以看到
第一条是触发侧去发送了一次请求到执行侧,发送的包的seq是756到1511
第二条是执行侧反馈的返回结果,执行侧直接发送了关闭连接的请求,并且ack只确认到756
第三条是触发侧确认了关闭请求,第四条执行侧确认了第三条的请求
所以2,3,4条是完整的走完了tcp的三次挥手操作,说明连接是执行侧主动关闭的
然后我们重新观察了一下正常的关闭连接的请求,发现每次都是由执行侧去关闭的连接,并且关闭的时间就是最后一次的请求的30s之后(空闲超时)
同时我们也从源码中可以看到超时时间默认就是30s

看到这里一切就都可以解释通了,由于执行侧30s超时时会断开连接,此时如果正好调度触发是从这台机器发起的,那么这次触发请求正好遇到执行侧关闭连接,执行侧发起关闭请求后,不会再接收来自触发侧的消息
所以应用由于无法读取请求的数据,所以报了eof错误
看明白报错的过程之后,我们来验证一下我们的猜想,看是否符合我们的预期
既然是30s超时会断开连接,那么如果我们的触发间隔设置为30s,那么就应该很容易碰到这种情况
因此,我将xxljob中发起触发请求的代码复制出来,然后将两次请求的间隔设置为30s,如下图:
通过下面的代码,可以很轻松的将问题复现出来,说明上面的分析是没有问题的

明白了问题所在,那么修复就比较简单了,我是采用修改空闲超时时间为10分钟,这样尽量避免调度切换和超时断开正好碰到一起
这种解决方式理论上仍然有报错的可能,但是概率大大降低了,同时也不需要修改xxljob源码,改动也比较小
如果有更好的解决方式欢迎评论区说明
测试类和修复类我都已经上传到csdn了,由于我比较贫穷,需要一些csdn的积分下载别的资源,所以希望各位支持一些积分给我
下载链接:https://download.csdn.net/download/wsss_fan/88299099
如果确实没有积分,可以联系我,我单独发给你
关于XXLJOB集群模式下调度失败的问题的更多相关文章
- Spark Streaming揭秘 Day31 集群模式下SparkStreaming日志分析(续)
Spark Streaming揭秘 Day31 集群模式下SparkStreaming日志分析(续) 今天延续昨天的内容,主要对为什么一个处理会分解成多个Job执行进行解析. 让我们跟踪下Job调用过 ...
- Spark Streaming揭秘 Day30 集群模式下SparkStreaming日志分析
Spark Streaming揭秘 Day30 集群模式下SparkStreaming日志分析 今天通过集群运行模式观察.研究和透彻的刨析SparkStreaming的日志和web监控台. Day28 ...
- 7.redis 集群模式的工作原理能说一下么?在集群模式下,redis 的 key 是如何寻址的?分布式寻址都有哪些算法?了解一致性 hash 算法吗?
作者:中华石杉 面试题 redis 集群模式的工作原理能说一下么?在集群模式下,redis 的 key 是如何寻址的?分布式寻址都有哪些算法?了解一致性 hash 算法吗? 面试官心理分析 在前几年, ...
- 就publish/subscribe功能看redis集群模式下的队列技术(一)
Redis 简介 Redis 是完全开源免费的,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中 ...
- 【Redis集群原理专题】分析一下相关的Redis集群模式下的脑裂问题!
技术格言 世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程. 什么是脑裂 字面含义 首先,脑裂从字面上理解就是脑袋裂开了,就是思想分家了,就是有了两个山头,就是有了 ...
- LB+nginx+tomcat7集群模式下的https请求重定向(redirect)后变成http的解决方案
0. 环境信息 Linux:Linux i-8emt1zr1 2.6.32-573.el6.x86_64 #1 SMP Wed Jul 1 18:23:37 EDT 2015 x86_64 x86_6 ...
- Redis集群模式下的redis-py-cluster方式读写测试
与MySQL主从复制,从节点可以分担部分读压力不一样,甚至可以增加slave或者slave的slave来分担读压力,Redis集群中的从节点,默认是不分担读请求的,从节点只作为主节点的备份,仅负责故障 ...
- Hadoop框架:集群模式下分布式环境搭建
本文源码:GitHub·点这里 || GitEE·点这里 一.基础环境配置 1.三台服务 准备三台Centos7服务,基础环境从伪分布式环境克隆过来. 133 hop01,134 hop02,136 ...
- Tomcat 集群模式下 Session 更新 Bug (redis memcached 及tomcat自已的集群)
从 excel 中导入数据入系统,我们用的是先上传文件至服务器再分析所上传的文件逐行导入. 就是执行了一循环,在当前循环位置标识一下客户端就知道执行的进度了,以前的方式 是用 session.setA ...
- 使用reids结合wcf实现集群模式下的聊天室功能
1.reids的特点 Redis数据库完全在内存中,使用磁盘仅用于持久性. 相比许多键值数据存储,Redis拥有一套较为丰富的数据类型(字符串,哈希,列表,集合,有序集合),. Redis可以将数据复 ...
随机推荐
- phpstudy-sqlilabs-less-4
题目:GET - Error based - Double Quotes - String 基于错误的GET双引号字符型注入 可能的注入点(不全) ' " ) ') ...
- web自动化10-窗口截图、验证码处理
窗口截图 1.是什么 说明:把当前操作的页面,截图保存到指定位置 2.代码中怎么使用? 说明:在Selenium中,提供了截图方法,我们只需要调用即可 方法: driver.get_screensho ...
- 代码随想录算法训练营Day31 贪心算法| 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II
代码随想录算法训练营 122.买卖股票的最佳时机II 题目链接:122.买卖股票的最佳时机II 给定一个数组,它的第 i个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润. ...
- PE 结构的三种地址
三种地址 (一)VA(虚拟地址):PE 文件被 Windows 加载到内存后的地址. (二) RVA(相对虚拟地址):PE 文件虚拟地址相对于映射基地址(对于 EXE 文件来说,映射基地址是 ...
- 【HMS Core】【In-App Purchases】应用内支付热门FAQ合集
近期收到很多开发者关于应用内支付服务的相关问题,主要集中在以下几个方面,今天和大家分享一下,希望给大家的开发集成带来帮助. [问题描述1] 近期,很多开发者收到关于"全面限制HTTP类型回 ...
- CKS 考试题整理 (14)-启用API Server认证
Context 由 kubeadm 创建的cluster 的kubernetes API 服务器,出于测试目的, 临时配置允许未经身份验证和未经授权的访问,授予匿名用户 cluster-admin 的 ...
- 4. SpringMVC获取请求参数
1. 通过 ServletAPI 获取 将 HttpServletRequest 作为控制器方法的形参 , 此时 HttpServletRequest 类型的参数表示封装了当前请求的请求报文的对象 ...
- Spring Cloud 之OpenFeign
Spring Cloud 之OpenFeign 一:简介 Feign是一个声明式(对比RestTemplate编程式)的服务客户端,即通过@FeignClient注解即可声明一个接口(interf ...
- C标准库 操作文件
C标准库 操作文件 数据持久化的两种方法:文件和数据库 文本文件和二进制文件 举个例子,写C++的代码,源代码为文本文件.编译出来的可执行文件(.exe)文件是二进制文件 文本文件 以文本的编码(AS ...
- 在DevExpress的GridView的列中,动态创建列的时候,绑定不同的编辑处理控件
在使用DevExpress的GridView的时候,我们为了方便,往往使用一些扩展函数,动态创建GridView列的编辑控件对象,然后我们可以灵活的对内容进行编辑或者使用一些弹出的对话框窗体进行处理内 ...