本篇內(nèi)容主要講解“怎么為kill job引入安全檢查點機制”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么為kill job引入安全檢查點機制”吧!
上林網(wǎng)站建設公司創(chuàng)新互聯(lián),上林網(wǎng)站設計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為上林千余家提供企業(yè)網(wǎng)站建設服務。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務好的上林做網(wǎng)站的公司定做!
XXL-JOB-ONION是基于XXL-JOB的二次開發(fā),我們基于XXL-JOB二次開發(fā)做了擴展,如添加ONION_BEAN運行模式、完善告警功能。
關于ONION_BEAN模式:
對于不需要分片的定時任務:通過繼承OnionJobHandler接口實現(xiàn),而不是使用XXL-JOB提供的注解;
對于需要分片的定時任務:通過繼承OnionShardingJobHandler接口實現(xiàn),而不是使用XXL-JOB提供的注解;
根據(jù)我們目前項目中的定時任務考察,發(fā)現(xiàn)定時任務大多都有一個共同點:每個定時任務都是從數(shù)據(jù)庫查詢一批數(shù)據(jù)出來處理,并且將每條數(shù)據(jù)轉為一個Runable放入業(yè)務隔離的線程池中執(zhí)行,例如:
@Component
public class OnionXxlJob implements OnionJobHandler {
@Override
public void doExecute(JobParam param) throws Exception {
// 實際從數(shù)據(jù)庫查詢
List orderIds = Arrays.asList(10000, 11111);
// 這里使用并行流模擬將每個訂單放入線程池處理
orderIds.parallelStream().forEach(orderService::handlerOrder);
}
}
由于定時任務每次執(zhí)行需要處理大批量數(shù)據(jù),可能執(zhí)行一次需要一個半小時,為解決每次版本更新或者應對突發(fā)數(shù)據(jù)量需要修改配置重啟時都需要等待定時任務執(zhí)行完成、想kill不敢kill的尷尬,我們?yōu)閤xl-job引入安全檢查點機制,靈感來源于jvm垃圾回收的安全檢查點機制。
為什么說想kill不敢kill?
雖然需要涉及到數(shù)據(jù)庫的操作都放在事務中,但并不是所有操作都能回滾,例如修改redis緩存數(shù)據(jù)、ES數(shù)據(jù)的操作都無法回滾(一般能放到事務提交之后的都放到后面執(zhí)行),如果處理數(shù)據(jù)的過程中需要調(diào)用第三方接口,那么會更復雜(這點我們已經(jīng)通過回放機制實現(xiàn))。
假設幾百個線程同時在處理,突然kill掉執(zhí)行中的任務,意味著可能幾百條數(shù)據(jù)處理出現(xiàn)問題,我們不得不找出這些數(shù)據(jù),將未完成的步驟完成。
我們先分析下XXL-JOB的kill job流程:xxl-job-admin前端發(fā)起kill請求,admin接收后向執(zhí)行器發(fā)起kill請求并攜帶jobId,執(zhí)行器根據(jù)jobId判斷當前任務是否再執(zhí)行,如果是則取消。
是否有一種方案,當定時任務管理員從后臺發(fā)起kill job操作時,先等待任務進入一個安全點再kill任務呢?
我們來看下面這張圖:
流程說明:
1、管理員在admin操作向執(zhí)行器發(fā)起kill請求、或執(zhí)行器自身為實現(xiàn)阻塞策略向自己發(fā)起kill請求;
2、執(zhí)行器接收到命令后,先獲取JobHandler,通知JobHandler的安全檢查點管理員,不讓新的Runable進入檢查點;
3、詢問JobHandler的安全檢查點計數(shù)器,可實現(xiàn)阻塞等待計數(shù)器的值為0再kill,或者異步等待計數(shù)器為0再kill;
4、XXL-JOB會為每個Job分配一個ID,通過每個JobId持有一個計數(shù)器可以隔離同Job不同時間段觸發(fā)的任務,當然,XXL-JOB也不允許同時執(zhí)行多個相同的Job;
安全檢查點:定時任務中Runable調(diào)用的業(yè)務方法
比如定時關閉超時未支付訂單的定時任務,查詢出的每個超時訂單,都會調(diào)用一個關閉訂單的方法,那么這個方法就可以設置為安全檢查點。
由于安全檢查點需要結合業(yè)務考慮,因此我們在設計上,只提供一個檢查點注解,讓使用者自己決定將哪個方法設置為安全檢查點、以及是否需要設置安全檢查點。
缺點:通過AOP方式,只能支持將public的方法設置為安全檢查點。
考慮過使用字節(jié)碼增強方式,強行將檢查行為插入private方法,但可能會導致應用啟動速度變慢,如果有需要的話,我們再考慮這種方法。
但我們也提供了編程式解決這個缺點,與Spring實現(xiàn)的事務機制一樣,安全檢查點支持注解方式使用,也支持編程式使用。
關于安全檢查管理員角色的設計:
只通過計數(shù)器統(tǒng)計當前進入安全檢查點方法的線程數(shù)無法做到“原子性”,在任務執(zhí)行的過程中,每時每刻都有新的Runable進入安全檢查點方法,也每時每刻都有Runable從安全檢查點方法出來。
通過安全檢查管理員控制Runable是否可以進入安全檢查點方法,在等待計數(shù)器值變?yōu)?之前,不再讓Runable進入安全檢查點,能夠解決“原子性”等待問題。
1、注解方式使用
注解方式使用要求方法必須是public的,與Spring注解式事務一樣,也存在不生效的問題。
2、編程方式使用
編程式使用也僅需三個步驟:
1、先判斷當前是否存在安全檢查點標志,如果存在則可以放棄執(zhí)行;
2、計數(shù)器加一,這是在OnionShardingJobHandler或OnionJobHandler接口中定義的default方法;
3、計數(shù)器減一,這是在OnionShardingJobHandler或OnionJobHandler接口中定義的default方法;
到此,相信大家對“怎么為kill job引入安全檢查點機制”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!