文章目录
问题描述
由于公司业务需要,数据库只能使用 sqlserver ,由于两个数据库语言上的差异,所以要进行改造。
xxl-job 代码及官方文档
源码:https://github.com/xuxueli/xxl-job
官方文档:https://www.xuxueli.com/xxl-job/
官方文档中说:
- 邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
- 默认提供邮件失败告警,可扩展短信、钉钉等方式。如果需要新增一种告警方式,只需要新增一个实现 “com.xxl.job.admin.core.alarm.JobAlarm” 接口的告警实现即可。可以参考默认提供邮箱告警实现 “EmailJobAlarm”。
需要操作的数据库表:
- xxl_job_log
需要改造的模块
可以看到,xxl-job 源码一共有三个模块:
- xxl-job-admin
- xxl-job-core
- xxl-job-executor
我们需要对 xxl-job-admin 模块进行改造
XxlJobScheduler
-
这个类是整个 xxl-job 的核心入口:任务监控、任务丢失、任务报警、日志、任务启动,都可以在这里找到,并进入到相关类中。
-
JobFailMonitorHelper.getInstance().start():该方法会进入错误任务的查询,以及发送报错邮件的功能
public class XxlJobScheduler {
private static final Logger logger = LoggerFactory.getLogger(XxlJobScheduler.class);
public void init() throws Exception {
// init i18n
initI18n();
// admin trigger pool start
JobTriggerPoolHelper.toStart();
// admin registry monitor run
JobRegistryHelper.getInstance().start();
// admin fail-monitor run
JobFailMonitorHelper.getInstance().start();
// admin lose-monitor run ( depend on JobTriggerPoolHelper )
JobCompleteHelper.getInstance().start();
// admin log report start
JobLogReportHelper.getInstance().start();
// start-schedule ( depend on JobTriggerPoolHelper )
JobScheduleHelper.getInstance().start();
logger.info(">>>>>>>>> init xxl-job admin success.");
}
}
mysql 查询报错邮件的方法
- 改造点一:这里 “!” 并不适用于 sqlserver,要重写相关的代码,有一点难度
- 改造点二:limit 也不适用于 sqlserver,如果使用 top,后面直接跟上 #{pagesize} 也会报错
<select id="findFailJobLogIds" resultType="long" >
SELECT id FROM `xxl_job_log`
WHERE !(
(trigger_code in (0, 200) and handle_code = 0)
OR
(handle_code = 200)
)
AND `alarm_status` = 0
ORDER BY id ASC
LIMIT #{pagesize}
</select>
由 LIMIT 引发的两种改造方案
- 方案一:top 后直接跟数字 1000,不再使用 #{pagesize}(原代码里传参的地方也是直接写死的 1000 )
- 方案二:删除 mybatis 依赖,引入 tk-mybatis,用 【Example example = new Example(XxlJobLog.class)】,在进行查询时,使用分页限制条数为 1000
两种方案的优缺点
- 方案一的优点是改造简单。缺点是由于使用了 top 命令,只能用于 sqlserver
- 方案二的优点是没有数据库的限制,无论 mysql 或 sqlserver 都可以使用。缺点是改造起来稍微有点繁琐(需要改造 pom 文件、使用分页、增加实现方法)
方案一改造
<select id="findFailJobLogIds" resultType="long" >
SELECT top 1000 id FROM xxl_job_log
WHERE (( handle_code = 0 and trigger_code not in (0,200) ) or (handle_code not in (0,200) ) )
AND alarm_status = 0
ORDER BY id ASC
</select>
方案二改造
public List<Long> findFailJobLogIds(int pagesize) {
Example example = new Example(XxlJobLog.class);
Example.Criteria criteria = example.createCriteria();
example.selectProperties("id");
example.orderBy("id");
criteria.andEqualTo("alarmStatus", 0);
criteria.andCondition(" (( handle_code = 0 and trigger_code not in (0,200) ) or (handle_code not in (0,200) ) ) ");
PageInfo<XxlJobLog> pageInfo = PageHelper.startPage(1, pagesize, false)
.doSelectPageInfo(() -> xxlJobLogDao.selectByExample(example));
List<XxlJobLog> logs = pageInfo.getList();
if (CollectionUtil.isEmpty(logs)) {
return new ArrayList<>(2);
} else {
return logs.stream().map(XxlJobLog::getId).collect(Collectors.toList());
}
}
邮箱配置
备注:
- user 和 form 要保持一致
- ssl-enable: true 有些博客配了这个,踩坑,不能配置,会报错
javamail:
host: xxx.163.com
port: 25
user: xxx@163.com
pass: xxx
form: xxx@163.com
auth: true