xxl-job是一個分佈式任務調度平臺,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展、開箱即用。我部門大部分定時任務調度都是基於xxl-job,諸如報表統計、定時數據同步等。
今天的素材來源於某天產品經理想在定時同步報表數據的基礎上,再增長一個手動觸發報表數據同步的功能。即在報表頁面上新增一個手動同步的按鈕,觸發該按鈕就能夠執行報表數據同步java
一、保留定時同步功能,同時新增手動同步二、手動同步的數據產生的效果要和定時數據同步的產生效果同樣git
一、方案1、新建一個手動調用的controller,controller觸發數據同步邏輯service
其實就是把寫在xxl-job執行器裏面的同步邏輯,再放到controller執行一遍github
二、方案2、新建一個手動調用的controller,在controller裏面直接觸發xxl-job執行器
在原先的定時器場景,咱們爲了不定時器裏面的同步邏輯還沒完成,下次定時器就觸發致使數據同步不許確,咱們在執行器裏面作一些手段進行規避,好比設置同步完成標誌位等。
若是基於方案一,方案看似可行,其實存在潛在的坑點。即定時器執行的時候,手動恰好觸發執行,或者反過來,手動觸發的時候,定時器也執行了。這樣就會致使數據同步執行屢次,致使數據不許確。spring
後面咱們調研了xxl-job,看到了xxl-job有提供restful風格觸發執行器的功能,這個功能簡直就是爲咱們量身定作,當手動調用的時候,觸發執行器,由於執行的是執行器裏面的調用邏輯,所以就會觸發咱們爲避免數據同步不許確所採起的手段springboot
其具體介紹能夠查看官網,其連接以下restful
https://www.xuxueli.com/xxl-job/#6.2 執行器 RESTful API併發
本例的核心代碼塊app
@RestController @RequestMapping(value = "xxl-job") @Api(tags = "xxl-job restful調度") @Profile("job") @Slf4j public class XxlJobController { @Autowired private XxljobClientHelper xxljobClientHelper; @ApiOperation(value = "手動觸發任務") @GetMapping("/run") public AjaxResult execute(){ String adminClientAddressUrl = xxljobClientHelper.getAdminClientAddressUrl(); String accessToken = xxljobClientHelper.getAccessToken(); log.info("adminClientAddressUrl:{},accessToken:{}", adminClientAddressUrl,accessToken); ExecutorBiz executorBiz = new ExecutorBizClient(adminClientAddressUrl, accessToken); ReturnT<String> retval = executorBiz.run(getTriggerParam()); log.info("retval:{}", JSON.toJSONString(retval)); // 200 表示正常、其餘失敗 if(retval.getCode() == 200){ return AjaxResult.success(); } return AjaxResult.error(retval.getMsg(),retval.getCode()); } private TriggerParam getTriggerParam(){ TriggerParam triggerParam = new TriggerParam(); // 任務ID // triggerParam.setJobId(15); // 任務標識 triggerParam.setExecutorHandler("demoJobHandler"); // 任務參數 triggerParam.setExecutorParams("手動觸發任務"); // 任務阻塞策略,可選值參考 com.xxl.job.core.enums.ExecutorBlockStrategyEnum triggerParam.setExecutorBlockStrategy(ExecutorBlockStrategyEnum.COVER_EARLY.name()); // 任務模式,可選值參考 com.xxl.job.core.glue.GlueTypeEnum triggerParam.setGlueType(GlueTypeEnum.BEAN.name()); // GLUE腳本代碼 triggerParam.setGlueSource(null); // GLUE腳本更新時間,用於斷定腳本是否變動以及是否須要刷新 triggerParam.setGlueUpdatetime(System.currentTimeMillis()); // 本次調度日誌ID triggerParam.setLogId(triggerParam.getJobId()); // 本次調度日誌時間 triggerParam.setLogDateTime(System.currentTimeMillis()); return triggerParam; } }
注: 代碼中的demoJobHandler,就是執行器裏面的調度方法。形以下dom
/** * 一、簡單任務示例(Bean模式) */ @XxlJob("demoJobHandler") public ReturnT<String> demoJobHandler(String param) throws Exception { XxlJobLogger.log("XXL-JOB, Hello World."); System.out.println("======================param:"+param+"================================隨機數:"+new Random().nextInt(1000)); return ReturnT.SUCCESS; }
若是選用方案一,也不是不行,就還得作一些改造,好比增長全局標誌位,並且在設置標誌位的時候,還要考慮併發場景下,可能出現的問題。所以還不如直接採用方案二。方案的選擇必定得要基於業務場景進行考量,不基於業務場景,談技術方案,很容易採坑分佈式
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-xxl-job-executor