Xxl-Job踩坑记录

乐云一
  • 笔记
  • note
About 1044 wordsAbout 3 min

Xxl-Job踩坑记录

将xxl-job二次开发了,然后在对接于拓展功能的时候发现了一些xxl-job在使用或性能上隐藏的坑;

接口请求超时

起初是设定业务方通过http接口调用xxl-job的增删改接口完成对任务的数据操作;

因此直接使用了内置提供的 XxlJobRemotingUtil 类的doPost方法进行请求,坑也就这样发现了;

由于http不具备一次请求的熔断或降级机制,唯一可控的就是设定http的请求超时时间。

见xxl-job的历史版本日志:

因为我使用的是xxljob的通讯方法,因此也直接沿用了他的3s超时的设置,问题也随之而至;

在调用删除任务接口时发现无论如何都会出现超时,通过查看代码:

	@Override
	public ReturnT<String> remove(int id) {
		XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
		if (xxlJobInfo == null) {
			return ReturnT.SUCCESS;
		}

		xxlJobInfoDao.delete(id);
		xxlJobLogDao.delete(id);
		xxlJobLogGlueDao.deleteByJobId(id);
		return ReturnT.SUCCESS;
	}

只是简单的三张表的删除,问题出在xxl_job_log表数据量莫名达到了千万级;

最终踩到的坑是xxlJob配置中的一个提示没注意到,清理日期定义了5天<7

### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能;
xxl.job.logretentiondays=30

但是经过这次超时体验,连夜将所有与调度中心通讯的http接口改造成了RPC接口。

最大任务数

因为有一个功能设计了开启、暂停,周期设置,因此选择了使用xxljob任务的概念实现功能;

并且由于用户可以最多创建99个这样的定时任务,所以对xxljob任务上线以及最多可以同时开启多少任务需要做到可见可控;

在git的 issues 中可以调研的提问:

https://github.com/xuxueli/xxl-job/issues/3071

https://github.com/xuxueli/xxl-job/issues/3079

可以知道,xxl-job默认是不支持这种用户级别创建调度任务的操作的;

但是可以通过部署多调度中心、修改等待队列大小和线程数配置可以达到理想的效果。

不过有一个一定要注意,在xxl-job的前端界面中的任务列表下拉框是全量拉取的,所以按照前端渲染的尿性,一次性渲染千条数据的时候页面就会出现卡顿的情况了;

线程并行的混乱

在并发的环境下,xxljob很多设计都会出现线程并行导致的混乱情况

一是 ReturnT 类,出现的结果集乱;

作为接口,api层的响应参数,并未用final进行修饰;

这也导致了在线程并行时是共享对象的情况,因此如果业务方需要调用api时需要考虑是否会涉及到多线程问题;

二时 日志 错乱

因为xxl-job是基于一个任务执行去记录日志,由此使用 ThreadLocal 保存日志文件地址当在任务中使用多线程时,两个任务使用同一个线程打印日志,threadLocal只会是其中一个任务的上下文信息(XxlJobContext),导致最终的错乱;

在源码 XxlJobHelper 类中

https://leyunone-img.oss-cn-hangzhou.aliyuncs.com/image/2024-04-12/6bc52616-03bf-4d6a-ae0a-552f6fdfd302.png

    private static InheritableThreadLocal<XxlJobContext> contextHolder = new InheritableThreadLocal<XxlJobContext>(); // support for child thread of job handler)

    public static void setXxlJobContext(XxlJobContext xxlJobContext){
        contextHolder.set(xxlJobContext);
    }

    public static XxlJobContext getXxlJobContext(){
        return contextHolder.get();
    }

但是这里有很难有更适合ThreadLocal的东西去记录一个线程任务的日志,因此目前还没有解决这个问题

Last update:
Contributors: LeYunone
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.14.7