日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

再见 Spring Task,这个定时任务框架真香!

發布時間:2025/3/11 javascript 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再见 Spring Task,这个定时任务框架真香! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近有朋友問到定時任務相關的問題。

于是,我簡單寫了一篇文章總結一下定時任務的一些概念以及一些常見的定時任務技術選型。希望能對小伙伴們有幫助!

個人能力有限。如果文章有任何需要補充/完善/修改的地方,歡迎在評論區指出,共同進步!

為什么需要定時任務?

我們來看一下幾個非常常見的業務場景:

  • 某系統凌晨要進行數據備份。

  • 某電商平臺,用戶下單半個小時未支付的情況下需要自動取消訂單。

  • 某媒體聚合平臺,每 10 分鐘動態抓取某某網站的數據為自己所用。

  • 某博客平臺,支持定時發送文章。

  • 某基金平臺,每晚定時計算用戶當日收益情況并推送給用戶最新的數據。

  • ......

  • 這些場景往往都要求我們在某個特定的時間去做某個事情。

    單機定時任務技術選型

    Timer

    java.util.Timer是 JDK 1.3 開始就已經支持的一種定時任務的實現方式。

    Timer 內部使用一個叫做 TaskQueue 的類存放定時任務,它是一個基于最小堆實現的優先級隊列。TaskQueue 會按照任務距離下一次執行時間的大小將任務排序,保證在堆頂的任務最先執行。這樣在需要執行任務時,每次只需要取出堆頂的任務運行即可!

    Timer 使用起來比較簡單,通過下面的方式我們就能創建一個 1s 之后執行的定時任務。

    //?示例代碼: TimerTask?task?=?new?TimerTask()?{public?void?run()?{System.out.println("當前時間:?"?+?new?Date()?+?"n"?+"線程名稱:?"?+?Thread.currentThread().getName());} }; System.out.println("當前時間:?"?+?new?Date()?+?"n"?+"線程名稱:?"?+?Thread.currentThread().getName()); Timer?timer?=?new?Timer("Timer"); long?delay?=?1000L; timer.schedule(task,?delay);//輸出: 當前時間:?Fri?May?28?15:18:47?CST?2021n線程名稱:?main 當前時間:?Fri?May?28?15:18:48?CST?2021n線程名稱:?Timer

    不過其缺陷較多,比如一個 Timer 一個線程,這就導致 Timer 的任務的執行只能串行執行,一個任務執行時間過長的話會影響其他任務(性能非常差),再比如發生異常時任務直接停止(Timer 只捕獲了 InterruptedException )。

    Timer 類上的有一段注釋是這樣寫的:

    *?This?class?does?not?offer?real-time?guarantees:?it?schedules*?tasks?using?the?<tt>Object.wait(long)</tt>?method.*Java?5.0?introduced?the?{@code?java.util.concurrent}?package?and*?one?of?the?concurrency?utilities?therein?is?the?{@link*?java.util.concurrent.ScheduledThreadPoolExecutor*?ScheduledThreadPoolExecutor}?which?is?a?thread?pool?for?repeatedly*?executing?tasks?at?a?given?rate?or?delay.??It?is?effectively?a?more*?versatile?replacement?for?the?{@code?Timer}/{@code?TimerTask}*?combination,?as?it?allows?multiple?service?threads,?accepts?various*?time?units,?and?doesn't?require?subclassing?{@code?TimerTask}?(just*?implement?{@code?Runnable}).??Configuring?{@code*?ScheduledThreadPoolExecutor}?with?one?thread?makes?it?equivalent?to*?{@code?Timer}.

    大概的意思就是:ScheduledThreadPoolExecutor 支持多線程執行定時任務并且功能更強大,是 Timer 的替代品。

    ScheduledExecutorService

    ScheduledExecutorService 是一個接口,有多個實現類,比較常用的是 ScheduledThreadPoolExecutor 。

    ScheduledThreadPoolExecutor 本身就是一個線程池,支持任務并發執行。并且,其內部使用 DelayQueue 作為任務隊列。

    //?示例代碼: TimerTask?repeatedTask?=?new?TimerTask()?{@SneakyThrowspublic?void?run()?{System.out.println("當前時間:?"?+?new?Date()?+?"n"?+"線程名稱:?"?+?Thread.currentThread().getName());} }; System.out.println("當前時間:?"?+?new?Date()?+?"n"?+"線程名稱:?"?+?Thread.currentThread().getName()); ScheduledExecutorService?executor?=?Executors.newScheduledThreadPool(3); long?delay??=?1000L; long?period?=?1000L; executor.scheduleAtFixedRate(repeatedTask,?delay,?period,?TimeUnit.MILLISECONDS); Thread.sleep(delay?+?period?*?5); executor.shutdown(); //輸出: 當前時間:?Fri?May?28?15:40:46?CST?2021n線程名稱:?main 當前時間:?Fri?May?28?15:40:47?CST?2021n線程名稱:?pool-1-thread-1 當前時間:?Fri?May?28?15:40:48?CST?2021n線程名稱:?pool-1-thread-1 當前時間:?Fri?May?28?15:40:49?CST?2021n線程名稱:?pool-1-thread-2 當前時間:?Fri?May?28?15:40:50?CST?2021n線程名稱:?pool-1-thread-2 當前時間:?Fri?May?28?15:40:51?CST?2021n線程名稱:?pool-1-thread-2 當前時間:?Fri?May?28?15:40:52?CST?2021n線程名稱:?pool-1-thread-2

    不論是使用 Timer 還是 ScheduledExecutorService 都無法使用 Cron 表達式指定任務執行的具體時間。

    Spring Task

    我們直接通過 Spring 提供的 @Scheduled 注解即可定義定時任務,非常方便!

    /*** cron:使用Cron表達式。?每分鐘的1,2秒運行*/ @Scheduled(cron?=?"1-2?*?*?*?*???") public?void?reportCurrentTimeWithCronExpression()?{log.info("Cron?Expression:?The?time?is?now?{}",?dateFormat.format(new?Date())); }

    我在大學那會做的一個 SSM 的企業級項目,就是用的 Spring Task 來做的定時任務。

    并且,Spring Task 還是支持 Cron 表達式 的。Cron 表達式主要用于定時作業(定時任務)系統定義執行時間或執行頻率的表達式,非常厲害,你可以通過 Cron 表達式進行設置定時任務每天或者每個月什么時候執行等等操作。咱們要學習定時任務的話,Cron 表達式是一定是要重點關注的。推薦一個在線 Cron 表達式生成器:http://cron.qqe2.com/ 。

    但是,Spring 自帶的定時調度只支持單機,并且提供的功能比較單一。之前寫過一篇文章:《5 分鐘搞懂如何在 Spring Boot 中 Schedule Tasks》

    Spring Task 底層是基于 JDK 的 ScheduledThreadPoolExecutor 線程池來實現的。

    優缺點總結:

    • 優點:簡單,輕量,支持 Cron 表達式

    • 缺點 :功能單一

    時間輪

    Kafka、Dubbo、ZooKeeper、Netty 、Caffeine 、Akka 中都有對時間輪的實現。

    時間輪簡單來說就是一個環形的隊列(底層一般基于數組實現),隊列中的每一個元素(時間格)都可以存放一個定時任務列表。

    時間輪中的每個時間格代表了時間輪的基本時間跨度或者說時間精度,加入時間一秒走一個時間格的話,那么這個時間輪的最高精度就是 1 秒(也就是說 3 s 和 3.9s 會在同一個時間格中)。

    下圖是一個有 12 個時間格的時間輪,轉完一圈需要 12 s。當我們需要新建一個 3s 后執行的定時任務,只需要將定時任務放在下標為 3 的時間格中即可。當我們需要新建一個 9s 后執行的定時任務,只需要將定時任務放在下標為 9 的時間格中即可。

    那當我們需要創建一個 13s 后執行的定時任務怎么辦呢?這個時候可以引入一叫做 圈數/輪數 的概念,也就是說這個任務還是放在下標為 3 的時間格中, 不過它的圈數為 2 。

    除了增加圈數這種方法之外,還有一種 多層次時間輪 (類似手表),Kafka 采用的就是這種方案。

    針對下圖的時間輪,我來舉一個例子便于大家理解。

    上圖的時間輪,第 1 層的時間精度為 1 ,第 2 層的時間精度為 20 ,第 3 層的時間精度為 400。假如我們需要添加一個 350s 后執行的任務 A 的話(當前時間是 0s),這個任務會被放在第 2 層(因為第二層的時間跨度為 20*20=400>350)的第 350/20=17 個時間格子。

    當第一層轉了 17 圈之后,時間過去了 340s ,第 2 層的指針此時來到第 17 個時間格子。此時,第 2 層第 17 個格子的任務會被移動到第 1 層。

    任務 A 當前是 10s 之后執行,因此它會被移動到第 1 層的第 10 個時間格子。

    這里在層與層之間的移動也叫做時間輪的升降級。參考手表來理解就好!

    時間輪比較適合任務數量比較多的定時任務場景,它的任務寫入和執行的時間復雜度都是 0(1)。

    分布式定時任務技術選型

    上面提到的一些定時任務的解決方案都是在單機下執行的,適用于比較簡單的定時任務場景比如每天凌晨備份一次數據。

    如果我們需要一些高級特性比如支持任務在分布式場景下的分片和高可用的話,我們就需要用到分布式任務調度框架了。

    通常情況下,一個定時任務的執行往往涉及到下面這些角色:

    • 任務 :首先肯定是要執行的任務,這個任務就是具體的業務邏輯比如定時發送文章。

    • 調度器 :其次是調度中心,調度中心主要負責任務管理,會分配任務給執行器。

    • 執行器 :最后就是執行器,執行器接收調度器分派的任務并執行。

    Quartz

    一個很火的開源任務調度框架,完全由Java寫成。Quartz 可以說是 Java 定時任務領域的老大哥或者說參考標準,其他的任務調度框架基本都是基于 Quartz 開發的,比如當當網的elastic-job就是基于quartz二次開發之后的分布式調度解決方案。

    使用 Quartz 可以很方便地與 Spring 集成,并且支持動態添加任務和集群。但是,Quartz 使用起來也比較麻煩,API 繁瑣。

    并且,Quzrtz 并沒有內置 UI 管理控制臺,不過你可以使用 quartzui 這個開源項目來解決這個問題。

    另外,Quartz 雖然也支持分布式任務。但是,它是在數據庫層面,通過數據庫的鎖機制做的,有非常多的弊端比如系統侵入性嚴重、節點負載不均衡。有點偽分布式的味道。

    優缺點總結:

    • 優點:可以與 Spring 集成,并且支持動態添加任務和集群。

    • 缺點 :分布式支持不友好,沒有內置 UI 管理控制臺、使用麻煩(相比于其他同類型框架來說)

    Elastic-Job

    Elastic-Job 是當當網開源的一個基于Quartz和ZooKeeper的分布式調度解決方案,由兩個相互獨立的子項目 Elastic-Job-Lite 和 Elastic-Job-Cloud 組成,一般我們只要使用 Elastic-Job-Lite 就好。

    ElasticJob 支持任務在分布式場景下的分片和高可用、任務可視化管理等功能。

    ElasticJob-Lite 的架構設計如下圖所示:

    從上圖可以看出,Elastic-Job 沒有調度中心這一概念,而是使用 ZooKeeper 作為注冊中心,注冊中心負責協調分配任務到不同的節點上。

    Elastic-Job 中的定時調度都是由執行器自行觸發,這種設計也被稱為去中心化設計(調度和處理都是執行器單獨完成)。

    @Component @ElasticJobConf(name?=?"dayJob",?cron?=?"0/10?*?*?*?*??",?shardingTotalCount?=?2,shardingItemParameters?=?"0=AAAA,1=BBBB",?description?=?"簡單任務",?failover?=?true) public?class?TestJob?implements?SimpleJob?{@Overridepublic?void?execute(ShardingContext?shardingContext)?{log.info("TestJob任務名:【{}】, 片數:【{}】, param=【{}】",?shardingContext.getJobName(),?shardingContext.getShardingTotalCount(),shardingContext.getShardingParameter());} }

    相關地址:

    • Github 地址:https://github.com/apache/shardingsphere-elasticjob。

    • 官方網站:https://shardingsphere.apache.org/elasticjob/index_zh.html 。

    優缺點總結:

    • 優點 :可以與 Spring 集成、支持分布式、支持集群、性能不錯

    • 缺點 :依賴了額外的中間件比如 Zookeeper(復雜度增加,可靠性降低、維護成本變高)

    XXL-JOB

    XXL-JOB 于 2015 年開源,是一款優秀的輕量級分布式任務調度框架,支持任務可視化管理、彈性擴容縮容、任務失敗重試和告警、任務分片等功能,

    根據 XXL-JOB 官網介紹,其解決了很多 Quartz 的不足。

    XXL-JOB 的架構設計如下圖所示:

    從上圖可以看出,XXL-JOB 由 調度中心執行器 兩大部分組成。調度中心主要負責任務管理、執行器管理以及日志管理。執行器主要是接收調度信號并處理。另外,調度中心進行任務調度時,是通過自研 RPC 來實現的。

    不同于 Elastic-Job 的去中心化設計, XXL-JOB 的這種設計也被稱為中心化設計(調度中心調度多個執行器執行任務)。

    和 Quzrtz 類似 XXL-JOB 也是基于數據庫鎖調度任務,存在性能瓶頸。不過,一般在任務量不是特別大的情況下,沒有什么影響的,可以滿足絕大部分公司的要求。

    不要被 XXL-JOB 的架構圖給嚇著了,實際上,我們要用 XXL-JOB 的話,只需要重寫 IJobHandler 自定義任務執行邏輯就可以了,非常易用!

    @JobHandler(value="myApiJobHandler") @Component public?class?MyApiJobHandler?extends?IJobHandler?{@Overridepublic?ReturnT<String>?execute(String?param)?throws?Exception?{//......return?ReturnT.SUCCESS;} }

    還可以直接基于注解定義任務。

    @XxlJob("myAnnotationJobHandler") public?ReturnT<String>?myAnnotationJobHandler(String?param)?throws?Exception?{//......return?ReturnT.SUCCESS; }

    相關地址:

    • Github 地址:https://github.com/xuxueli/xxl-job/。

    • 官方介紹:https://www.xuxueli.com/xxl-job/ 。

    優缺點總結:

    • 優點:開箱即用(學習成本比較低)、與 Spring 集成、支持分布式、支持集群、內置了 UI 管理控制臺。

    • 缺點:不支持動態添加任務(如果一定想要動態創建任務也是支持的,參見:xxl-job issue277)。

    PowerJob

    非常值得關注的一個分布式任務調度框架,分布式任務調度領域的新星。目前,已經有很多公司接入比如 OPPO、京東、中通、思科。

    這個框架的誕生也挺有意思的,PowerJob 的作者當時在阿里巴巴實習過,阿里巴巴那會使用的是內部自研的 SchedulerX(阿里云付費產品)。實習期滿之后,PowerJob 的作者離開了阿里巴巴。想著說自研一個 SchedulerX,防止哪天 SchedulerX 滿足不了需求,于是 PowerJob 就誕生了。

    更多關于 PowerJob 的故事,小伙伴們可以去看看 PowerJob 作者的視頻 《我和我的任務調度中間件》。簡單點概括就是:“游戲沒啥意思了,我要扛起了新一代分布式任務調度與計算框架的大旗!”。

    由于 SchedulerX 屬于人民幣產品,我這里就不過多介紹。PowerJob 官方也對比過其和 QuartZ、XXL-JOB 以及 SchedulerX。

    總結

    這篇文章中,我主要介紹了:

    • 定時任務的相關概念 :為什么需要定時任務、定時任務中的核心角色、分布式定時任務。

    • 定時任務的技術選型 :XXL-JOB 2015 年推出,已經經過了很多年的考驗。XXL-JOB 輕量級,并且使用起來非常簡單。雖然存在性能瓶頸,但是,在絕大多數情況下,對于企業的基本需求來說是沒有影響的。PowerJob 屬于分布式任務調度領域里的新星,其穩定性還有待繼續考察。ElasticJob 由于在架構設計上是基于 Zookeeper ,而 XXL-JOB 是基于數據庫,性能方面的話,ElasticJob 略勝一籌。

    這篇文章并沒有介紹到實際使用,但是,并不代表實際使用不重要。我在寫這篇文章之前,已經動手寫過相應的 Demo。像 Quartz,我在大學那會就用過。不過,當時用的是 Spring 。為了能夠更好地體驗,我自己又在 Spring Boot 上實際體驗了一下。如果你并沒有實際使用某個框架,就直接說它并不好用的話,是站不住腳的。

    總結

    以上是生活随笔為你收集整理的再见 Spring Task,这个定时任务框架真香!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 青娱乐在线播放 | 色婷婷综合久久久久中文一区二区 | 98久久 | 国产精品无码av在线有声小说 | 桃色激情网 | 国产精品无码久久久久久 | 波多野结衣在线影院 | 成人免费av在线 | 亚洲欧洲色 | va婷婷| 青青草婷婷 | 黑人巨茎大战欧美白妇 | 免费a在线观看 | 成人国产精品免费观看视频 | 毛茸茸free性熟hd | 色综合色综合网色综合 | 人妻久久一区二区三区 | 91精品久久人妻一区二区夜夜夜 | 黄色网址视频 | 欧美精品久久久 | 永久av在线免费观看 | 色欲AV无码精品一区二区久久 | 亚洲经典在线观看 | 在线国产播放 | 狠狠干天天射 | 狠狠艹av | 9.1成人免费看片 | 成人资源站 | 最近高清中文在线字幕在线观看 | 97插插插| 爱情岛论坛亚洲品质自拍视频 | 精品国产97 | 网站黄色在线观看 | 97在线观视频免费观看 | 亚洲国产精品国自产拍久久 | 国产97色在线 | 日韩 | 国产农村妇女精品 | av网站在线免费看 | 国产一区二区视频网站 | 日韩综合另类 | juliaann欧美二区三区 | 五月婷婷综合网 | 国产精品海角社区 | www网站在线观看 | av美女网站 | 国产av不卡一区二区 | 欧美激情片一区二区 | 国产丝袜av| 久久久久久久久久一区二区三区 | 免费亚洲视频 | 亚洲骚片| 日本黄页视频 | 国模无码国产精品视频 | 久久久久久av无码免费网站下载 | 日韩不卡在线播放 | av片网址 | 香蕉视频在线观看网站 | 中文字幕日韩久久 | 天天噜夜夜噜 | 麻豆影视 | 香蕉国产在线视频 | 一区二区三区国产精品 | av一级大片| 天天干妹子 | 女人舌吻男人茎视频 | 性色av网址 | 成人国产毛片 | 欧美日韩偷拍视频 | 在线综合网 | 国产精品日本 | 国产精品一区二区三区免费视频 | 国产一级二级在线 | 免费午夜激情 | 亚洲高清在线一区 | 国产成人一区二区三区电影 | 日本h在线 | 午夜性刺激免费视频 | 日韩少妇毛片 | 日本网站在线看 | 青青草娱乐在线 | 最新中文字幕2019 | 97超碰碰碰 | 那里有毛片看 | 色播一区二区 | avwww.| 国产最新毛片 | 高潮一区二区三区乱码 | 波多野吉衣在线视频 | 台湾佬美性中文娱乐网 | 久久午夜夜伦鲁鲁片 | 免费亚洲一区 | 天天色天天色 | 日日夜夜免费精品视频 | 国产精品tv | 天天爽夜夜爽夜夜爽精品视频 | 天堂久久久久久 | 97se.com| 禁漫天堂下载18 | 深夜小视频在线观看 |