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獲得執行個體進行反射
@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版本沒有提供多使用者及權限管理
原文位址
https://www.cnblogs.com/ingxx/p/11274508.html