每臺虛機在同一時間都會執行定時任務:html
Tomcatgit |
Nginxspring |
Tomcatshell |
嘗試解決:將任務單獨拆出放入一臺虛機(TASK)。架構
Nginx併發 |
Tomcatapp |
TASK框架 |
Tomcat分佈式 |
產生新的問題:性能
1.即使TASK 100%可靠永遠不宕。也有極大的停機風險,不肯定在停機期間是否有任務被遺漏(misfire)。
2.任務更多,更復雜,佔愈來愈多的資源,性能問題凸顯,任務隊列阻塞風險。
Nginx |
Tomcat |
Tomcat |
DB(quartz) |
以後看了眼quartz官方logo,感受本身萌萌的。
萌不過三天。發現這個定時任務策略要修改,
一樣,下面這個任務不須要作,取消掉
也沒法及時監控:報錯了嗎,運行成功了嗎?
隨着業務發展暴露出愈來愈多的問題:
例如:
----截圖摘自沈建林「分佈式調度系統介紹」中的五個問題
集思廣益造輪子:
Quartz,Xxl-job,elastic-job,tbschedule,uncode-schedule,Opencron
在分佈式環境中如何將任務集羣中分散的、可靠性差的任務統一化管理和調度,實現分佈式部署的管理方式,這就是分佈式任務調度。
http://www.javashuo.com/article/p-onabuvoj-bc.html
XXL-JOB框架2015-11月發佈1.0.RELEASE。
2016-01月,大衆點評接入XXL-JOB,內部別名《Ferrari》。 自2016-01-21接入至2017-12-01期間,該系統已調度約100萬次,通過數個大版本的更新,系統的任務模型、UI交互模型以及底層調度通信模型都有了較大的優化和提高,核心功能更加穩定高效。
Elastic-Job分爲Elastic-Job-Lite和Elastic-Job-Cloud
http://code.taobao.org/p/tbschedule/src/
http://code.taobao.org/p/tbschedule/wiki/tbschedule-quick-start/
https://gitee.com/uncode/uncode-schedule/releases
2.2.1.1.1Example1
固然也支持cron表達式以下,運行結果略。
2.2.1.1.2Example2-CronTrigger Misfire
Misfire策略
withMisfireHandlingInstructionDoNothing:不觸發當即執行,等待下次調度; withMisfireHandlingInstructionIgnoreMisfires:以錯過的第一個頻率時間馬上開始執行; withMisfireHandlingInstructionFireAndProceed:以當前時間爲觸發頻率馬上觸發一次執行;
準備工做:
Job:
Misfires strategy1:
withMisfireHandlingInstructionIgnoreMisfires:以錯過的第一個頻率時間馬上開始執行;
Misfires strategy2:
withMisfireHandlingInstructionDoNothing:不觸發當即執行,等待下次調度;
Misfires strategy3:
withMisfireHandlingInstructionFireAndProceed:以當前時間爲觸發頻率馬上觸發一次執行
2.2.1.2.1Quartz組件
QuartzSchedulerThread :負責執行向QuartzScheduler註冊的觸發Trigger的工做的線程。
ThreadPool:Scheduler使用一個線程池做爲任務運行的基礎設施,任務經過共享線程池中的線程提供運行效率。
QuartzSchedulerResources:包含建立QuartzScheduler實例所需的全部資源(JobStore,ThreadPool等)。
SchedulerFactory :提供用於獲取調度程序實例的客戶端可用句柄的機制。
JobStore: 經過類實現的接口,這些類要爲org.quartz.core.QuartzScheduler的使用提供一個org.quartz.Job和org.quartz.Trigger存儲機制。做業和觸發器的存儲應該以其名稱和組的組合爲惟一性。
QuartzScheduler :這是Quartz的核心,它是org.quartz.Scheduler接口的間接實現,包含調度org.quartz.Jobs,註冊org.quartz.JobListener實例等的方法。
Scheduler :這是Quartz Scheduler的主要接口,表明一個獨立運行容器。調度程序維護JobDetails和觸發器的註冊表。 一旦註冊,調度程序負責執行做業,當他們的相關聯的觸發器觸發(當他們的預約時間到達時)。
Trigger :具備全部觸發器通用屬性的基本接口,描述了job執行的時間出發規則。 - 使用TriggerBuilder實例化實際觸發器。
JobDetail :傳遞給定做業實例的詳細信息屬性。 JobDetails將使用JobBuilder建立/定義。
Job:要由表示要執行的「做業」的類實現的接口。只有一個方法 void execute(jobExecutionContext context)
(jobExecutionContext 提供調度上下文各類信息,運行時數據保存在jobDataMap中)
Job有個子接口StatefulJob ,表明有狀態任務。
有狀態任務不可併發,前次任務沒有執行完,後面任務處於阻塞等到。
2.2.1.2.2組件關係簡要
2.2.1.2.3生命週期
只列重點不展開,用Quartz官網Example1
2.2.1.2.3.1Scheduler
(1)Scheduler
Instantiate()這是一個近千行的方法,
(1-1)Scheduler Members
(2)JobStore
(3)ThreadExecutor
(4)QuartzSchedulerThread
(4-1)run()
(4-2)sigLock.await()
(5)Job run
2.2.1.2.3.2Scheduler-start()-notifyAll()
2.3.1.1.1JobStore
2.3.1.1.2Lock & Trigger
2.3.1.1.3時序圖
2.3.1.2.1功能概述
2.3.1.2.2架構
Nginx |
Tomcat |
Tomcat |
Zookeeper |
Spring task |
Quartz |
2.3.1.2.3ZKScheduleManager
繼承ThreadPoolTaskScheduler,重寫下圖方法:
在子類和父類中任選一個方法對比,好比scheduleAtFixedRate()方法:
子類:
父類:
發現便是在第一個入參Runnable task包裝了一個taskWrapper(task)
在容器啓動以及心跳刷新服務的時候,會在zookeeper上建立節點
在節點
」/uncode_test/schedule/task/helloWorld#hi」
下面會有ip+uuid+seqno,在taskWrapper()中的isOwner便是根據此標識字符串:
「192.168.236.1$FA2165482C644A899076A9542BF68C25$0000000008」
每一個機器本身均持有各自的標識字符串,任一時刻至多隻有一臺匹配的機器,持有匹配字符串的機器才能執行
2.3.1.2.4心跳-刷新任務節點
2.3.1.2.5Uncode schedule與Quartz集成
2.3.1.2.6監控
2.3.1.3.1配置
2.3.1.3.2任務/分片 demo
2.3.2.1.1功能概述
http://www.javashuo.com/article/p-onabuvoj-bc.html
2.3.2.1.2調度關係
Jetty |
Admin |
Xxl-job-core.jar |
Jetty |
2.3.2.1.3管理中心
路由策略
2.3.2.1.4管理端服務AdminBiz
XxlJobDynamicScheduler
服務發現+失敗預警+遠程觸發
JobRegistryMonitorHelper.getInstance().start();
執行器註冊到registry,管理中心不斷掃描同步註冊進來的執行器至group中。
Server Registry |
Admin |
Executor |
Server Group |
JobFailMonitorHelper.getInstance().start();
(3)RemotehttpJobBean
參見Uncode-Schedule與Quartz集成
(4)XxlJobTrigger策略模式按策略觸發任務
(5)NetComClientProxy代理模式遠程調用Executor
(6)路由策略
(6-1)第一個
(6-2)一致hash
(6-3)分片廣播
對比其它策略的相同方法:
(6-4)failover
(6-5)busyover
(6-5)其它
其它策略:最後一個,輪詢,隨機,最不常用,最近最久不使用:略。
也可本身定製。
(7)Misfire
XXL-JOB默認misfire規則爲:withMisfireHandlingInstructionDoNothing
2.3.2.1.5執行器端服務ExecutorBiz
(1)XxlJobExecutor
(1-1)NetComClientProxy代理模式遠程調用Admin
(1-2)加載任務bean
(1-3)服務註冊
(2)JettyServerHandler準備執行任務
(3)ExecutorBizImpl如何執行任務
(4)TriggerParam
搶佔式:誰先得到資源誰就能執行,這種模式沒法將單個任務的數據交給其它節點協同處理,通常用於處理數據量較小,任務較多的場景下。
協同式:能夠將單個任務處理的數據分配到多個JVM中處理,提升數據的並行處理能力,可以充分利用計算機資源。
TbSchedule:
Uncode schedule:
TbSchedule:
Uncode schedule:
做業分片只是個邏輯概念,分片和實際數據其實框架是不作任何匹配關係的。而根據分片項和實際業務如何關聯按業務自定義。