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