docker部署xxl-job 通用反射执行器
原因
最近在公司写一些job,公司使用的是spring boot提供的注解形式实现的。
这样在自测的时候很麻烦,而且测试提测的时候需要修改cron表达式->提交git->jenkins打包重启
解决方案
查阅资料后决定选用任务调度平台,有很多优秀的任务调度平台,选择xxl-job是因为文档清晰、使用简单、基于远程RPC调用、官方提供spring boot例子。
部署
首先需要执行官网提供的sql
使用docker下载镜像 这里最新版本是2.0.2
docker pull xuxueli/xxl-job-admin:2.0.2
然后运行docker镜像 注意修改参数
docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://数据库地址:3306/xxl-job?Unicode=true&characterEncoding=UTF-8 --spring.datasource.password=数据库密码 --spring.mail.host=smtp.163.com --spring.mail.username=邮箱名 --spring.mail.password=邮箱密码 --xxl.job.login.password=登录密码" -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin --privileged=true -d xuxueli/xxl-job-admin:2.0.2
注意一些参数如邮箱可以省略
在项目中配置
这里配置使用官网示例中的spring boot配置
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@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(initMethod = "start", destroyMethod = "destroy")
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
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;
}
}
官网给出的执行器配置说明
### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志保存天数 [选填] :值大于3时生效,启用执行器Log文件定期清理功能,否则不生效;
xxl.job.executor.logretentiondays=-1
执行器
官方给出了不少执行器,但是要在原有项目上改造需要自己写执行器,当然可以使用一个任务写一个执行器,这样执行器就会很多,很难以维护。所以这里采用反射的方式
首先是全类名执行器使用反射的方式
@Component
@JobHandler(value = "BeanByClassHandler")
public class BeanByClassHandler extends IJobHandler {
@Autowired
private ApplicationContext applicationContext;
//根据完整类名 通过反射执行指定方法
@Override
public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log(param);
if (param == null || param.equals("")) {
return new ReturnT<>(ReturnT.FAIL_CODE, "参数不能为空!");
}
String[] split = param.split(",");
if (split == null || split.length < 2) {
return new ReturnT<>(ReturnT.FAIL_CODE, "参数格式错误,应为 完整类名,方法名");
}
Class taskBeanClass = null;
try {
taskBeanClass = Class.forName(split[0]);
} catch (Exception e) {
return new ReturnT<>(ReturnT.FAIL_CODE, "类" + split[0] + "不存在");
}
Method method = null;
try {
method = taskBeanClass.getMethod(split[1]);
} catch (Exception e) {
return new ReturnT<>(ReturnT.FAIL_CODE, "方法" + split[1] + "不存在");
}
Object o = applicationContext.getBean(taskBeanClass);
if (o == null) {
return new ReturnT<>(ReturnT.FAIL_CODE, "在Application中类不存在");
}
try {
method.invoke(o);
} catch (Exception e) {
return new ReturnT<>(ReturnT.FAIL_CODE, "方法执行失败");
}
return new ReturnT<>(ReturnT.SUCCESS_CODE, "执行成功");
}
}
这样全类名很长所以可以使用spring管理beanName获得实例进行反射
@Component
@JobHandler(value = "BeanByNameHandler")
public class BeanByNameHandler extends IJobHandler {
@Autowired
private ApplicationContext applicationContext;
//根据spring管理的bean name获取指定类
@Override
public ReturnT<String> execute(String param) throws Exception {
XxlJobLogger.log(param);
if (param == null || param.equals("")) {
return new ReturnT<>(ReturnT.FAIL_CODE, "参数不能为空!");
}
String[] split = param.split(",");
if (split == null || split.length < 2) {
return new ReturnT<>(ReturnT.FAIL_CODE, "参数格式错误,应为bean名称,方法名");
}
Object o = applicationContext.getBean(split[0]);
if(o == null){
return new ReturnT<>(ReturnT.FAIL_CODE,"类在applicationContext中不存在");
}
Method method;
try {
method = o.getClass().getMethod(split[1]);
}catch (Exception e){
return new ReturnT<>(ReturnT.FAIL_CODE,"方法"+split[1]+"不存在");
}
try {
method.invoke(o);
}catch (Exception e){
return new ReturnT<>(ReturnT.FAIL_CODE,"调用方法失败");
}
return new ReturnT<>(ReturnT.SUCCESS_CODE,"调用job成功");
}
}
调用
在web界面新建任务 参数为 全类名,方法名即可。如下图所示
当然也可以执行shell脚本
缺点
- xxl-job只支持mysql数据库,公司使用的Oracle 所以docker需要运行一个mysql数据库
- xxl-job截至2.0.2版本没有提供多用户及权限管理
补充
好消息xxl-job在最新的 6.27 版本 v2.1.2 Release Notes[2019-12-12]中支持了方法级别的Handler注解,不需要再写反射啦!
docker部署xxl-job 通用反射执行器的更多相关文章
- Docker 部署前后端项目
Docker 部署前后端项目 平生不会相思,才会相思,便害相思. 简介:都是被逼的,从零开始一个Docker 部署九个微服务和三个前端项目.其中,这些服务需要用到Nacos.MySQL.Nginx.E ...
- Docker 部署xxl-job 报错:xxl-rpc remoting error(connect timed out), for url : xxxxxx
使用Docker 部署的xxl-job,当调度中心和执行器部署在不同的容器内,此时xxl-job调用执行器的服务就会报: address:http://172.0.0.1:8841/ code:500 ...
- ASP.NET Core开发-Docker部署运行
ASP.NET Core开发Docker部署,.NET Core支持Docker 部署运行.我们将ASP.NET Core 部署在Docker 上运行. 大家可能都见识过Docker ,今天我们就详细 ...
- Docker部署Hadoop集群
Docker部署Hadoop集群 2016-09-27 杜亦舒 前几天写了文章"Hadoop 集群搭建"之后,一个朋友留言说希望介绍下如何使用Docker部署,这个建议很好,Doc ...
- Atiti qq空间破解(3)------------gui图形化通用cli执行器atiuse
Atiti qq空间破解(3)------------gui图形化通用cli执行器atiuse 结构:::命令行+以及反馈log框1 cli_guiUI/index.htm1 /AtiPlatf_c ...
- 程序开发使用docker部署
我们公司自己研发了一套 grand-line 系统,使用 docker 来部署项目. 我是第一批小白鼠,一开始网络差,build 一次要半个小时,连接进入 web shell 也很慢,部署一个微信项目 ...
- 我使用celery以及docker部署遇到的问题
首先我本机测试时没有问题的,但是在线上docker中,任务一直显示 "Sending due task".超时的任务是 django orm update 操作,本地不会出现这样的 ...
- Docker部署SDN环境
2014-12-03 by muzi Docker image = Java class Docker container = Java object 前言 5月份的时候,当我还是一个大学生的时候,有 ...
- 在生产环境使用Docker部署应用
导读 Docker现在越来越流行,但是真正在生产环境部署Docker还是个比较新的概念,还没有一个标准的流程.作者是ROR的程序员,作者结合平时的部署经验,联系Docker的特点,向大家分享了其在生产 ...
随机推荐
- Spring 之Aop实现日志记录
Aop实现见代码,简单demo实现 package com.idcos.automate.config; import com.idcos.automate.dal.auto.dao.dcos.Dco ...
- [apue] 等待子进程的那些事儿
谈到等待子进程,首先想到的就是SIGCHLD信号与wait函数族,本文试图厘清二者的方方面面,以及组合使用时可能不小心掉进去的坑. 1. 首先谈单独使用SIGCHLD的场景.下面是一段典型的代码片段: ...
- 使用Python脚本伪造指定时间区间的数据库备份
为监管需求,需要保留时间非常长的数据库备份.存储代价太大.所以存在了,临时抱佛脚,伪造备份.. 以下脚本功能,在于根据一个备份,复制出一段时间的备份.并且更改备份的文件时间戳.可以用shell轻松写出 ...
- IDEA中Maven依赖包下载不了的问题解决方案汇总
第一种方案: 第二种方案:下面的几个不要选择. 第三种方案:可能是某一个 dependency 依赖无法下载,导致整个项目都报错 打开具体的报错的maven项目的pom.xml.试着去删除一些 dep ...
- Codeforces 777D:Cloud of Hashtags(水题)
http://codeforces.com/problemset/problem/777/D 题意:给出n道字符串,删除最少的字符使得s[i] <= s[i+1]. 思路:感觉比C水好多啊,大概 ...
- HDU 5791:Two(DP)
http://acm.hdu.edu.cn/showproblem.php?pid=5791 Two Problem Description Alice gets two sequences A ...
- 『开发技巧』Keras自定义对象(层、评价函数与损失)
1.自定义层 对于简单.无状态的自定义操作,你也许可以通过 layers.core.Lambda 层来实现.但是对于那些包含了可训练权重的自定义层,你应该自己实现这种层. 这是一个 Keras2.0 ...
- 热度3年猛增20倍,Serverless&云开发的技术架构全解析
『 作为一个不断发展的新兴技术, Serverless 热度的制高点已然到来.』 或许,Google Trends 所显示的 3 年猛增 20 倍的" Serverless " 搜 ...
- spring springMVC Struts2 区别
Spring: Spring是IOC和AOP的容器框架,Spring是一个通用解决方案, 最大的用处就是通过Ioc/AOP解耦, 降低软件复杂性, 所以Spring可以结合SpringMVC等很多其他 ...
- pdfminer获取整页文本
#! python2 # coding: utf-8 import sys from cStringIO import StringIO from pdfminer import pdfinterp ...