如何通過編碼的方式手動觸發xxl-job執行器


前言

xxl-job是一個分布式任務調度平台,其核心設計目標是開發迅速、學習簡單、輕量級、易擴展、開箱即用。我部門大部分定時任務調度都是基於xxl-job,諸如報表統計、定時數據同步等。
今天的素材來源於某天產品經理想在定時同步報表數據的基礎上,再增加一個手動觸發報表數據同步的功能。即在報表頁面上新增一個手動同步的按鈕,觸發該按鈕就可以執行報表數據同步

需求分析

1、保留定時同步功能,同時新增手動同步

2、手動同步的數據產生的效果要和定時數據同步的產生效果一樣

解決思路

1、方案一、新建一個手動調用的controller,controller觸發數據同步邏輯service

其實就是把寫在xxl-job執行器里面的同步邏輯,再放到controller執行一遍

2、方案二、新建一個手動調用的controller,在controller里面直接觸發xxl-job執行器

解決方案分析

在原先的定時器場景,我們為了避免定時器里面的同步邏輯還沒完成,下次定時器就觸發導致數據同步不准確,我們在執行器里面做一些手段進行規避,比如設置同步完成標志位等。
如果基於方案一,方案看似可行,其實存在潛在的坑點。即定時器執行的時候,手動剛好觸發執行,或者反過來,手動觸發的時候,定時器也執行了。這樣就會導致數據同步執行多次,導致數據不准確。

后面我們調研了xxl-job,看到了xxl-job有提供restful風格觸發執行器的功能,這個功能簡直就是為我們量身定做,當手動調用的時候,觸發執行器,因為執行的是執行器里面的調用邏輯,因此就會觸發我們為避免數據同步不准確所采取的手段

如何通過restful風格手動觸發xxl-job執行器執行

其具體介紹可以查看官網,其鏈接如下

https://www.xuxueli.com/xxl-job/#6.2 執行器 RESTful API

本例的核心代碼塊

@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,就是執行器里面的調度方法。形如下

  /**
     * 1、簡單任務示例(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;
    }

總結

如果選用方案一,也不是不行,就還得做一些改造,比如增加全局標志位,而且在設置標志位的時候,還要考慮並發場景下,可能出現的問題。因此還不如直接采用方案二。方案的選擇一定得要基於業務場景進行考量,不基於業務場景,談技術方案,很容易采坑

demo鏈接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-xxl-job-executor


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM