xxl-job学习使用
首先先介绍一下xxl-job,这是出自大众点评许雪里(xxl就是作者名字的拼音首字母)的开源项目,官网上介绍这是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。跟elasticjob不同,xxl-job环境依赖于mysql,不用ZooKeeper,这也是最大的不同。
elasticjob的初衷是为了面对高并发复杂的业务,即使是在业务量大,服务器多的时候也能做好任务调度,尽可能的利用服务器的资源。使用ZooKeeper使其具有高可用、一致性的,而且还具有良好的扩展性。官网上写
elasticjob是无中心化的,通过ZooKeeper的选举机制选举出主服务器,如果主服务器挂了,会重新选举新的主服务器。因此elasticjob具有良好的扩展性和可用性,但是使用和运维有一定的复杂
对xxl-job进行配置和创建 XxlJobSpringExecutor 执行器
@Slf4j @Configuration public class XxlJobConfig { @Value("${xxl.job.admin.addresses}") private String adminAddresses; @Value("${xxl.job.executor.appname}") private String appName; @Value("${xxl.job.executor.ip}") private String ip; @Value("${xxl.job.executor.port}") private int port; @Value("${xxl.job.accessToken}") private String accessToken; @Value("${xxl.job.executor.logpath}") private String logPath; @Value("${xxl.job.executor.logretentiondays}") private int logRetentionDays; @Bean public XxlJobSpringExecutor xxlJobExecutor() { // 创建 XxlJobSpringExecutor 执行器 XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); xxlJobSpringExecutor.setAdminAddresses(adminAddresses); xxlJobSpringExecutor.setAppname(appName); xxlJobSpringExecutor.setIp(ip); xxlJobSpringExecutor.setPort(port); xxlJobSpringExecutor.setAccessToken(accessToken); xxlJobSpringExecutor.setLogPath(logPath); xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); // 返回 return xxlJobSpringExecutor; } }
使用java api 通过xxl-job接口进行调度
@Slf4j
@Service
public class CronTaskServiceImpl implements CronTaskService {
@Value("${xxl.job.admin.username}")
private String xxlUserName;
@Value("${xxl.job.admin.password}")
private String xxlPassword;
@Value("${xxl.job.admin.addresses}")
private String xxlAddresses;
@Override
public BasicResultVO saveCronTask(XxlJobInfo xxlJobInfo) {
Map<String, Object> params = JSON.parseObject(JSON.toJSONString(xxlJobInfo), Map.class);
String path = xxlJobInfo.getId() == null ? xxlAddresses + XxlJobConstant.INSERT_URL
: xxlAddresses + XxlJobConstant.UPDATE_URL;
HttpResponse response;
ReturnT returnT = null;
try {
// 调用xxl-job的接口将任务信息sava到xxl-job中;然后xxl-job会根据executorHandler 的值找到对应的Handler
// 比如executorHandler 的值是
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
returnT = JSON.parseObject(response.body(), ReturnT.class);
// 插入时需要返回Id,而更新时不需要
if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
if (path.contains(XxlJobConstant.INSERT_URL)) {
Integer taskId = Integer.parseInt(String.valueOf(returnT.getContent()));
return BasicResultVO.success(taskId);
} else if (path.contains(XxlJobConstant.UPDATE_URL)) {
return BasicResultVO.success();
}
}
} catch (Exception e) {
log.error("CronTaskService#saveTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(xxlJobInfo), JSON.toJSONString(returnT));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
}
@Override
public BasicResultVO deleteCronTask(Integer taskId) {
String path = xxlAddresses + XxlJobConstant.DELETE_URL;
HashMap<String, Object> params = MapUtil.newHashMap();
params.put("id", taskId);
HttpResponse response;
ReturnT returnT = null;
try {
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
returnT = JSON.parseObject(response.body(), ReturnT.class);
if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
return BasicResultVO.success();
}
} catch (Exception e) {
log.error("CronTaskService#deleteCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(returnT));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
}
@Override
public BasicResultVO startCronTask(Integer taskId) {
String path = xxlAddresses + XxlJobConstant.RUN_URL;
HashMap<String, Object> params = MapUtil.newHashMap();
params.put("id", taskId);
HttpResponse response;
ReturnT returnT = null;
try {
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
returnT = JSON.parseObject(response.body(), ReturnT.class);
if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
return BasicResultVO.success();
}
} catch (Exception e) {
log.error("CronTaskService#startCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(returnT));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
}
@Override
public BasicResultVO stopCronTask(Integer taskId) {
String path = xxlAddresses + XxlJobConstant.STOP_URL;
HashMap<String, Object> params = MapUtil.newHashMap();
params.put("id", taskId);
HttpResponse response;
ReturnT returnT = null;
try {
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
returnT = JSON.parseObject(response.body(), ReturnT.class);
if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
return BasicResultVO.success();
}
} catch (Exception e) {
log.error("CronTaskService#stopCronTask fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(returnT));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
}
@Override
public BasicResultVO getGroupId(String appName, String title) {
String path = xxlAddresses + XxlJobConstant.JOB_GROUP_PAGE_LIST;
HashMap<String, Object> params = MapUtil.newHashMap();
params.put("appname", appName);
params.put("title", title);
HttpResponse response = null;
try {
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
Integer id = JSON.parseObject(response.body()).getJSONArray("data").getJSONObject(0).getInteger("id");
if (response.isOk() && id != null) {
return BasicResultVO.success(id);
}
} catch (Exception e) {
log.error("CronTaskService#getGroupId fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(response.body()));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(response.body()));
}
@Override
public BasicResultVO createGroup(XxlJobGroup xxlJobGroup) {
Map<String, Object> params = JSON.parseObject(JSON.toJSONString(xxlJobGroup), Map.class);
String path = xxlAddresses + XxlJobConstant.JOB_GROUP_INSERT_URL;
HttpResponse response;
ReturnT returnT = null;
try {
response = HttpRequest.post(path).form(params).cookie(getCookie()).execute();
returnT = JSON.parseObject(response.body(), ReturnT.class);
if (response.isOk() && ReturnT.SUCCESS_CODE == returnT.getCode()) {
return BasicResultVO.success();
}
} catch (Exception e) {
log.error("CronTaskService#createGroup fail,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(returnT));
}
return BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR, JSON.toJSONString(returnT));
}
/**
* 获取xxl cookie
*
* @return String
*/
private String getCookie() {
Map<String, Object> params = MapUtil.newHashMap();
params.put("userName", xxlUserName);
params.put("password", xxlPassword);
params.put("randomCode", IdUtil.fastSimpleUUID());
String path = xxlAddresses + XxlJobConstant.LOGIN_URL;
HttpResponse response = null;
try {
response = HttpRequest.post(path).form(params).execute();
if (response.isOk()) {
List<HttpCookie> cookies = response.getCookies();
StringBuilder sb = new StringBuilder();
for (HttpCookie cookie : cookies) {
sb.append(cookie.toString());
}
return sb.toString();
}
} catch (Exception e) {
log.error("CronTaskService#createGroup getCookie,e:{},param:{},response:{}", Throwables.getStackTraceAsString(e)
, JSON.toJSONString(params), JSON.toJSONString(response));
}
return null;
}
}
调度执行的handler
@Service @Slf4j public class CronTaskHandler { @Autowired private TaskHandler taskHandler; @Autowired private ThreadPoolUtils threadPoolUtils; private DtpExecutor dtpExecutor = CronAsyncThreadPoolConfig.getXxlCronExecutor(); /** * 处理后台的 austin 定时任务消息 */ @XxlJob("austinJob") public void execute() { log.info("CronTaskHandler#execute messageTemplateId:{} cron exec!", XxlJobHelper.getJobParam()); threadPoolUtils.register(dtpExecutor); Long messageTemplateId = Long.valueOf(XxlJobHelper.getJobParam()); dtpExecutor.execute(() -> taskHandler.handle(messageTemplateId)); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix