大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情”
1、最近身边蛮多朋友被裁员,让我深切感受到这个糟糕的大环境,而且不是说个人能力不行🙅,先大环境不咋地,然后再到很多公司业务不咋地,然后按业务线来搞,所以那些被裁的也不要太难过。包括最近我们bg也有大动作
可以说在大环境下,危机四伏~
2、当然博主也是有些人脉,前几天有个大佬跟我打探前同事的情况,因为投了他们公司,不得不说圈子蛮小的,哈哈
3、平时周末感觉没什么事干,打球成了为数不多的兴趣,庆幸还是有点肌肉,哈哈
为啥会谈到这个话题呢?
我记得很久之前,技术群有个oppo的大佬,广告营销组的,看业务组就知道是核心业务组,听说他们也对xxl-job进行改造,我当时就很好奇,这个框架不是很便捷吗,难道有什么不足?
那么今天我们就来聊聊xxl-job框架的不足
这是大众点评许雪里开源的一个轻量级分布式任务调度框架,有个任务界面,将任务执行handle注册到调度中心,然后新建任务,里面会指定执行器名称,corn,失败重试次数,报警邮箱,执行相关参数,任务名称,我们可以看到比spring 自带定时器强大很多,然后也自带了全局任务执行结果的展示图。
这个需要我们进去源码里头看个究竟
我们从xxl-job任务执行curl找到执行的方法,新增促发,首先它会判断当前任务以往执行的情况,如果是比较快的,就丢到fast线程池,然后你一直执行high慢,那么把你丢到slow线程池。这样好处是避免那些执行时间很慢的任务阻塞了其他任务。
到这里其实平平无奇,就是搂出任务信息,任务组的信息(有多少个执行器注册上去),是否执行分片任务,这个是比较好的设计,就是当我们任务比较多的时候,可以通过集群来提高整个系统的处理速度。
到这里是执行的过程,类似http,拿到执行参数,点一下,嗖~返回请求结果,然后记录到日志里头
那么关键我们看下线程池
private ThreadPoolExecutor fastTriggerPool = null;\
private ThreadPoolExecutor slowTriggerPool = null;\
\
public void start(){\
fastTriggerPool = new ThreadPoolExecutor(\
10,\
XxlJobAdminConfig.*getAdminConfig*().getTriggerPoolFastMax(),\
60L,\
TimeUnit.*SECONDS*,\
new LinkedBlockingQueue<Runnable>(1000),\
new ThreadFactory() {\
@Override\
public Thread newThread(Runnable r) {\
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode());\
}\
});\
\
slowTriggerPool = new ThreadPoolExecutor(\
10,\
XxlJobAdminConfig.*getAdminConfig*().getTriggerPoolSlowMax(),\
60L,\
TimeUnit.*SECONDS*,\
new LinkedBlockingQueue<Runnable>(2000),\
new ThreadFactory() {\
@Override\
public Thread newThread(Runnable r) {\
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode());\
}\
});\
}
我们可以看到核心线程数10个,满格是200个线程,然后缓冲区快的是1000,慢的线程池是2000
了解过线程池的小伙伴就知道,当我们超过max线程池+缓存区的数量会执行拒绝策略,采用默认的也就是丢弃策略,这就回答了为啥超过上千并发任务的时候就会导致任务丢失。
那么我来提个问题:上千任务并发正常吗?我认为一般小公司是无法达到这样的qps的,如果是大公司,然后大家的调度中心又是同一个,那么就会出现这种情况,比如说200个研发,每人写6个晚上9点执行的任务,好了炸了~
解决方案
我们可以通过之前美团介绍的动态更新线程池的方式,调大整个线程池的缓冲区数量,其次可以重写拒绝策略,当超过最大缓存数量的时候,先往数据库塞,然后当有空间的时候慢慢的读出然后删除待执行的记录。
我来介绍下这种情况,就是每5分钟去拉增量数据的场景,如果中途有段任务没了,那么你的数据也会丢失,xxl-job的做法是重试,我们通过领域的思想来看,确实任务丢失是属于调度中心的问题,包括网络延迟等等问题,但是重试是无法彻底解决这个问题
解决方案
就是在我们业务端去缓存这个拉取的时间,比如说上次拉取是什么时候,如果中间有段丢失了,那我们下次任务就从上次丢失的地方开始拉数据,这样就补齐了。
这个要求开发同学有一定的定时任务处理经验,包括参数也应该设计为可配置化,如果出现什么意外,可以进行暗箱操作,比如说昨天数据没有同步到,那我们改下定时任务执行参数执行即可
其实嘛,这个问题不应该发生的,为什么呢?
你的代码有问题,你把锅丢给任务调度中心,还要人家去优化,这是人才。kill任务的情况,意味着任务是有问题的,那么我们需要打印剔除掉的相关数据(无法回滚),比如说mq、redis,然后人工根据日志进行手动回滚
然后修复任务的逻辑,发版上线,这不就完事了吗,鹅鹅鹅🦢
好吧,我没啥要讲的,看完有帮助的话记得点赞关注~宝子们