一、使用背景
目前項目中,采用的是微服務框架,由於在微服務中,存在需要定時的任務。但如果定時任務維護在每個微服務下,當微服務部署多個實例的情況下,會出現定事任務多次執行的情況。並且在解決問題的基礎上,希望能夠實現動態修改任務的定時時間,可以通過頁面對定時任務進行控制。
二、XXL-JOB簡單介紹
首先,XXL-JOB是一個輕量級分布式任務調度平台,內容采用了Quartz定時框架實現,服務之間通信通過RPC的方式實現。
其次,在功能方面:
- 支持通過web頁面對任務進行增刪改查操作
- 支持動態修改任務狀態、啟動、停止等,即時生效。
- 支持多種阻塞處理策略,如串行、丟棄后續調度、覆蓋之前調度
- 支持超時控制、失敗重試、郵件報警等處理
- ......
詳情可參考官方網站:http://www.xuxueli.com/xxl-job
三、服務端實現過程
1、XXL-JOB源碼下載:
github地址:https://github.com/xuxueli/xxl-job
其中,xxl-job-core為核心代碼塊,xxl-job-admin為任務調度中心管理模塊,部署的話,部署xxl-job-admin即可。
2、數據庫創建:
sql文件為:xxl-job/doc/db/tables_xxl_job.sql,在mysql數據庫中執行該sql,能生成新的數據庫xxl-job及相關的數據庫表xxl_job_*。
目前從源碼來看,暫時只支持mysql數據庫,如需支持其他數據庫,可在源碼上進行相關的修改:如mybatis的配置、sql語句等。
3、xxl-job-admin模塊配置修改:
修改xxl-job-admin下的配置文件:application.properties
在配置文件中,主要需要修改數據庫地址(spring.datasource.url)、用戶名(spring.datasource.username)、密碼的配置(spring.datasource.password)為實際的部署環境。
端口號(server.port)默認為8080,可修改。
訪問地址(server.context-path)默認為xxl-job-admin,可修改。
4、啟動xxl-job-admin微服務:
啟動成功后,可通過訪問http://localhost:8080/xxl-job-admin來對任務調度中心進行訪問。
用戶名密碼默認為:admin/123456
四、客戶端(微服務模塊)實現過程:
1、引用依賴:
pom.xml中,增加依賴:
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.0.2</version> </dependency>
2、修改配置文件:
本文采用yml配置文件,增加配置如下:
xxl:
job:
admin:
addresses: http://localhost:8080/xxl-job-admin
executor:
ip:
port: 9999
logpath: /data/applogs/xxl-job/jobhandler
appname: plat-job
accessToken:
其中ip可不填,會自動識別注冊。
3、編寫Configuration類
此處需要注意版本差異,由於服務器端采用的是V2+,客戶端也需要采用V2+。不然會有異常。
V2+的配置類代碼如下:
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @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; private int logRetentionDays=-1; @Bean(initMethod = "start", destroyMethod = "destroy") public XxlJobSpringExecutor xxlJobExecutor() { System.out.println(">>>>>>>>>>> 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; } }
4、編寫Handler類(實際處理任務):
代碼如下所示:
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
@JobHandler(value="TestHandler") @Component public class TestHandler extends IJobHandler { @Override public ReturnT<String> execute(String param) throws Exception { System.out.println("執行了TestHandler一次");
return SUCCESS; } }
在上面代碼中,Handler的命名為“TestHandler”,此命名需要是唯一的,后續再服務器中配置會用到。
5、啟動客戶端(微服務):
啟動成功后,會自動在服務器中,增加一個名為【plat-job】的執行器,用來執行定時任務。
五、服務器端頁面中進行配置:
1、修改執行器:
訪問服務器頁面登錄成功后,點擊執行器管理,如圖:
對執行器進行編輯,注冊方式改為【手動錄入】,機器地址寫入客戶端(微服務)具體的ip:port后,點擊保存。
2、任務管理編輯:
點擊【任務管理】頁簽【新增】按鈕,執行器選擇plat-job,JobHandler編寫為【TestHandler】,Cron為定時計划,如圖所示:
保存后,可點擊【執行】按鈕,查看是否調用了客戶端的Handler處理。在此不再演示。如可執行,則點擊【啟動】按鈕,會在定時計划內,再次調用Handler處理。
同時,在對任務的Cron進行修改、保存后,會動態的更新定時計划,實現了項目中的期望。
由於每個微服務的ip和port可以在執行器的機器地址中,通過逗號分隔的方式,可增加多個客戶端的地址,則解決了項目中多實例的問題。