<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          學會這10種定時任務(wù),我有點飄了

          共 19907字,需瀏覽 40分鐘

           ·

          2021-04-16 12:02

          大家好我是蘇三,又跟大家見面了。

          前言

          最近有幾個讀者私信給我,問我他們的業(yè)務(wù)場景,要用什么樣的定時任務(wù)。確實,在不用的業(yè)務(wù)場景下要用不同的定時任務(wù),其實我們的選擇還是挺多的。我今天給大家總結(jié)10種非常實用的定時任務(wù),總有一種是適合你的。

          一. linux自帶的定時任務(wù)

          crontab

          不知道你有沒有遇到過這種場景:有時需要臨時統(tǒng)計線上的數(shù)據(jù),然后導出到excel表格中。這種需求有時較為復雜,光靠寫sql語句是無法滿足需求的,這就需要寫java代碼了。然后將該程序打成一個jar包,在線上環(huán)境執(zhí)行,最后將生成的excel文件下載到本地。

          為了減小對線上環(huán)境的影響,我們一般會選擇在凌晨1-2點,趁用戶量少的時候,執(zhí)行統(tǒng)計程序。(其實凌晨4點左右,用戶才是最少的)

          由于時間太晚了,我們完全沒必要守在那里等執(zhí)行結(jié)果,一個定時任務(wù)就能可以搞定。

          那么,這種情況用哪種定時任務(wù)更合適呢?

          答案是:linux系統(tǒng)的crontab。(不過也不排除有些項目沒部署在linux系統(tǒng)中)

          運行crontab -e,可以編輯定時器,然后加入如下命令:

          0 2 * * * /usr/local/java/jdk1.8/bin/java -jar /data/app/tool.jar > /logs/tool.log &

          就可以在每天凌晨2點,定時執(zhí)行tool.jar程序,并且把日志輸出到tool.log文件中。當然你也可以把后面的執(zhí)行java程序的命令寫成shell腳本,更方便維護。

          使用這種定時任務(wù)支持方便修改定時規(guī)則,有界面可以統(tǒng)一管理配置的各種定時腳本。

          crontab命令的基本格式如下:

          crontab [參數(shù)] [文件名]

          如果沒有指定文件名,則接收鍵盤上輸入的命令,并將它載入到crontab

          參數(shù)功能對照表如下:

          參數(shù)功能
          -u指定用戶
          -e編輯某個用戶的crontab文件內(nèi)容
          -l顯示某個用戶的crontab文件內(nèi)容
          -r刪除某用戶的crontab文件
          -i刪除某用戶的crontab文件時需確認

          以上參數(shù),如果沒有使用-u指定用戶,則默認使用的當前用戶。

          通過crontab -e命令編輯文件內(nèi)容,具體語法如下:

          [分] [小時] [日期] [月] [星期] 具體任務(wù)

          其中:

          • 分,表示多少分鐘,范圍:0-59
          • 小時,表示多少小時,范圍:0-23
          • 日期,表示具體在哪一天,范圍:1-31
          • 月,表示多少月,范圍:1-12
          • 星期,表示多少周,范圍:0-7,0和7都代表星期日

          還有一些特殊字符,比如:

          • *代表如何時間,比如:*1*** 表示每天凌晨1點執(zhí)行。
          • /代表每隔多久執(zhí)行一次,比如:*/5 **** 表示每隔5分鐘執(zhí)行一次。
          • ,代表支持多個,比如:10 7,9,12 *** 表示在每天的7、9、12點10分各執(zhí)行一次。
          • -代表支持一個范圍,比如:10 7-9 *** 表示在每天的7、8、9點10分各執(zhí)行一次。

          此外,順便說一下crontab需要crond服務(wù)支持,crondlinux下用來周期地執(zhí)行某種任務(wù)的一個守護進程,在安裝linux操作系統(tǒng)后,默認會安裝crond服務(wù)工具,且crond服務(wù)默認就是自啟動的。crond進程每分鐘會定期檢查是否有要執(zhí)行的任務(wù),如果有,則會自動執(zhí)行該任務(wù)。

          可以通過以下命令操作相關(guān)服務(wù):

          service crond status // 查看運行狀態(tài)
          service crond start //啟動服務(wù)
          service crond stop //關(guān)閉服務(wù)
          service crond restart //重啟服務(wù)
          service crond reload //重新載入配置

          使用crontab的優(yōu)缺點:

          • 優(yōu)點:方便修改定時規(guī)則,支持一些較復雜的定時規(guī)則,通過文件可以統(tǒng)一管理配好的各種定時腳本。

          • 缺點:如果定時任務(wù)非常多,不太好找,而且必須要求操作系統(tǒng)是linux,否則無法執(zhí)行。

          二. jdk自帶的定時任務(wù)

          1.Thread

          各位親愛的朋友,你沒看錯,Thread類真的能做定時任務(wù)。如果你看過一些定時任務(wù)框架的源碼,你最后會發(fā)現(xiàn),它們的底層也會使用Thread類。

          實現(xiàn)這種定時任務(wù)的具體代碼如下:

          public static void init() {
          new Thread(() -> {
          while (true) {
          try {
          System.out.println("doSameThing");
          Thread.sleep(1000 * 60 * 5);
          } catch (Exception e) {
          log.error(e);
          }
          }
          }).start();
          }

          使用Thread類可以做最簡單的定時任務(wù),在run方法中有個while的死循環(huán)(當然還有其他方式),執(zhí)行我們自己的任務(wù)。有個需要特別注意的地方是,需要用try...catch捕獲異常,否則如果出現(xiàn)異常,就直接退出循環(huán),下次將無法繼續(xù)執(zhí)行了。

          這種方式做的定時任務(wù),只能周期性執(zhí)行,不能支持定時在某個時間點執(zhí)行。

          此外,該線程可以定義成守護線程,在后臺默默執(zhí)行就好。

          使用場景:比如項目中有時需要每隔10分鐘去下載某個文件,或者每隔5分鐘去讀取模板文件生成靜態(tài)html頁面等等,一些簡單的周期性任務(wù)場景。

          使用Thread類的優(yōu)缺點:

          • 優(yōu)點:這種定時任務(wù)非常簡單,學習成本低,容易入手,對于那些簡單的周期性任務(wù),是個不錯的選擇。

          • 缺點:不支持指定某個時間點執(zhí)行任務(wù),不支持延遲執(zhí)行等操作,功能過于單一,無法應(yīng)對一些較為復雜的場景。

          2.Timer

          Timer類是jdk專門提供的定時器工具,用來在后臺線程計劃執(zhí)行指定任務(wù),在java.util包下,要跟TimerTask一起配合使用。

          Timer類其實是一個任務(wù)調(diào)度器,它里面包含了一個TimerThread線程,在這個線程中無限循環(huán)從TaskQueue中獲取TimerTask(該類實現(xiàn)了Runnable接口),調(diào)用其run方法,就能異步執(zhí)行定時任務(wù)。我們需要繼承TimerTask類,實現(xiàn)它的run方法,在該方法中加上自己的業(yè)務(wù)邏輯。

          實現(xiàn)這種定時任務(wù)的具體代碼如下:

          public class TimerTest {

              public static void main(String[] args) {
                  Timer timer = new Timer();
                  timer.schedule(new TimerTask() {
                      @Override
                      public void run() {
                          System.out.println("doSomething");
                      }
                  },2000,1000);
              }
          }

          先實例化一個Timer類,然后調(diào)用它的schedule方法,在該方法中實例化TimerTask類,業(yè)務(wù)邏輯寫在run方法中。schedule方法最后的兩次參數(shù)分別表示:延遲時間間隔時間,單位是毫秒。上面例子中,設(shè)置的定時任務(wù)是每隔1秒執(zhí)行一次,延遲2秒執(zhí)行。

          主要包含6個方法:

          • schedule(TimerTask task, Date time), 指定任務(wù)task在指定時間time執(zhí)行
          • schedule(TimerTask task, long delay), 指定任務(wù)task在指定延遲delay后執(zhí)行
          • schedule(TimerTask task, Date firstTime,long period),指定任務(wù)task在指定時間firstTime執(zhí)行后,進行重復固定延遲頻率peroid的執(zhí)行
          • schedule(TimerTask task, long delay, long period), 指定任務(wù)task 在指定延遲delay 后,進行重復固定延遲頻率peroid的執(zhí)行
          • scheduleAtFixedRate(TimerTask task,Date firstTime,long period), 指定任務(wù)task在指定時間firstTime執(zhí)行后,進行重復固定延遲頻率peroid的執(zhí)行
          • scheduleAtFixedRate(TimerTask task, long delay, long period), 指定任務(wù)task 在指定延遲delay 后,進行重復固定延遲頻率peroid的執(zhí)行

          不過使用Timer實現(xiàn)定時任務(wù)有以下問題:

          1. 由于Timer是單線程執(zhí)行任務(wù),如果其中一個任務(wù)耗時非常長,會影響其他任務(wù)的執(zhí)行。
          2. 如果TimerTask拋出RuntimeException,Timer會停止所有任務(wù)的運行。

          使用Timer類的優(yōu)缺點:

          • 優(yōu)點:非常方便實現(xiàn)多個周期性的定時任務(wù),并且支持延遲執(zhí)行,還支持在指定時間之后支持,功能還算強大。

          • 缺點:如果其中一個任務(wù)耗時非常長,會影響其他任務(wù)的執(zhí)行。并且如果TimerTask拋出RuntimeExceptionTimer會停止所有任務(wù)的運行,所以阿里巴巴開發(fā)者規(guī)范中不建議使用它。

          3.ScheduledExecutorService

          ScheduledExecutorService是JDK1.5+版本引進的定時任務(wù),該類位于java.util.concurrent并發(fā)包下。

          ScheduledExecutorService是基于多線程的,設(shè)計的初衷是為了解決Timer單線程執(zhí)行,多個任務(wù)之間會互相影響的問題。

          它主要包含4個方法:

          • schedule(Runnable command,long delay,TimeUnit unit),帶延遲時間的調(diào)度,只執(zhí)行一次,調(diào)度之后可通過Future.get()阻塞直至任務(wù)執(zhí)行完畢。
          • schedule(Callable<V> callable,long delay,TimeUnit unit),帶延遲時間的調(diào)度,只執(zhí)行一次,調(diào)度之后可通過Future.get()阻塞直至任務(wù)執(zhí)行完畢,并且可以獲取執(zhí)行結(jié)果。
          • scheduleAtFixedRate,表示以固定頻率執(zhí)行的任務(wù),如果當前任務(wù)耗時較多,超過定時周期period,則當前任務(wù)結(jié)束后會立即執(zhí)行。
          • scheduleWithFixedDelay,表示以固定延時執(zhí)行任務(wù),延時是相對當前任務(wù)結(jié)束為起點計算開始時間。

          實現(xiàn)這種定時任務(wù)的具體代碼如下:

          public class ScheduleExecutorTest {

              public static void main(String[] args) {
                  ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
                  scheduledExecutorService.scheduleAtFixedRate(() -> {
                      System.out.println("doSomething");
                  },1000,1000, TimeUnit.MILLISECONDS);
              }
          }

          調(diào)用ScheduledExecutorService類的scheduleAtFixedRate方法實現(xiàn)周期性任務(wù),每隔1秒鐘執(zhí)行一次,每次延遲1秒再執(zhí)行。

          這種定時任務(wù)是阿里巴巴開發(fā)者規(guī)范中用來替代Timer類的方案,對于多線程執(zhí)行周期性任務(wù),是個不錯的選擇。

          ScheduledExecutorService的優(yōu)缺點:

          • 優(yōu)點:基于多線程的定時任務(wù),多個任務(wù)之間不會相關(guān)影響,支持周期性的執(zhí)行任務(wù),并且?guī)а舆t功能。

          • 缺點:不支持一些較復雜的定時規(guī)則。

          三. spring支持的定時任務(wù)

          1.spring task

          spring taskspring3以上版本自帶的定時任務(wù),實現(xiàn)定時任務(wù)的功能時,需要引入spring-context包,目前它支持:xml注解 兩種方式。

          1. 項目實戰(zhàn)

          由于xml方式太古老了,我們以springboot項目中注解方式為例。

          第一步,在pom.xml文件中引入spring-context相關(guān)依賴。

          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
          </dependency>

          第二步,在springboot啟動類上加上@EnableScheduling注解。

          @EnableScheduling
          @SpringBootApplication
          public class Application {

              public static void main(String[] args) {
                  new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);
              }
          }

          第三步,使用@Scheduled注解定義定時規(guī)則。

          @Service
          public class SpringTaskTest {

              @Scheduled(cron = "${sue.spring.task.cron}")
              public void fun() {
                  System.out.println("doSomething");
              }
          }

          第四步,在applicationContext.properties文件中配置參數(shù):

          sue.spring.task.cron=*/10 * * * * ?

          這樣就能每隔10秒執(zhí)行一次fun方法了。

          2. cron規(guī)則

          spring4以上的版本中,cron表達式包含6個參數(shù):

          [秒] [分] [時] [日期] [月] [星期]

          還支持幾個常用的特殊符號:

          • *:表示任何時間觸發(fā)任務(wù)
          • ,:表示指定的時間觸發(fā)任務(wù)
          • -:表示一段時間內(nèi)觸發(fā)任務(wù)
          • /:表示從哪一個時刻開始,每隔多長時間觸發(fā)一次任務(wù)。
          • ?:表示用于月中的天和周中的天兩個子表達式,表示不指定值。

          cron表達式參數(shù)具體含義:

          1. 秒,取值范圍:0-59,支持*,-/
          2. 分,取值范圍:0-59,支持*,-/
          3. 時,取值范圍:0-23,支持*,-/
          4. 日期,取值范圍:1-31,支持*,-/。比秒多了?,表示如果指定的星期觸發(fā)了,則配置的日期變成無效。
          5. 月,取值范圍:1-12,支持*,-/
          6. 星期,取值范圍:1~7,1代表星期天,6代表星期六,其他的以此類推。支持*,-/?。比秒多了?,表示如果指定的日期觸發(fā)了,則配置的星期變成無效。

          常見cron表達式使用舉例:

          • 0 0 0 1 * ?  每月1號零點執(zhí)行
          • 0 0 2 * * ?  每天凌晨2點執(zhí)行
          • 0 0 2 * * ?  每天凌晨2點執(zhí)行
          • 0 0/5 11 * * ? 每天11點-11點55分,每隔5分鐘執(zhí)行一次
          • 0 0 18 ? * WED 每周三下午6點執(zhí)行

          spring task先通過ScheduledAnnotationBeanPostProcessor類的processScheduled方法,解析和收集Scheduled注解中的參數(shù),包含:cron表達式。

          然后在ScheduledTaskRegistrar類的afterPropertiesSet方法中,默認初始化一個單線程的ThreadPoolExecutor執(zhí)行任務(wù)。

          對spring task感興趣的小伙伴,可以加我微信找我私聊。

          使用spring task的優(yōu)缺點:

          • 優(yōu)點:spring框架自帶的定時功能,springboot做了非常好的封裝,開啟和定義定時任務(wù)非常容易,支持復雜的cron表達式,可以滿足絕大多數(shù)單機版的業(yè)務(wù)場景。單個任務(wù)時,當前次的調(diào)度完成后,再執(zhí)行下一次任務(wù)調(diào)度。

          • 缺點:默認單線程,如果前面的任務(wù)執(zhí)行時間太長,對后面任務(wù)的執(zhí)行有影響。不支持集群方式部署,不能做數(shù)據(jù)存儲型定時任務(wù)。

          2.spring quartz

          quartzOpenSymphony開源組織在Job scheduling領(lǐng)域的開源項目,是由java開發(fā)的一個開源的任務(wù)日程管理系統(tǒng)。

          quartz能做什么?

          • 作業(yè)調(diào)度:調(diào)用各種框架的作業(yè)腳本,例如shell,hive等。
          • 定時任務(wù):在某一預定的時刻,執(zhí)行你想要執(zhí)行的任務(wù)。

          架構(gòu)圖如下:

          quartz包含的主要接口如下:

          • Scheduler 代表調(diào)度容器,一個調(diào)度容器中可以注冊多個JobDetail和Trigger。
          • Job 代表工作,即要執(zhí)行的具體內(nèi)容。
          • JobDetail 代表具體的可執(zhí)行的調(diào)度程序,Job是這個可執(zhí)行程調(diào)度程序所要執(zhí)行的內(nèi)容。
          • JobBuilder 用于定義或構(gòu)建JobDetail實例。
          • Trigger 代表調(diào)度觸發(fā)器,決定什么時候去調(diào)。
          • TriggerBuilder 用于定義或構(gòu)建觸發(fā)器。
          • JobStore 用于存儲作業(yè)和任務(wù)調(diào)度期間的狀態(tài)。

          1. 項目實戰(zhàn)

          我們還是以springboot集成quartz為例。

          第一步,在pom.xml文件中引入quartz相關(guān)依賴。

          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-quartz</artifactId>
          </dependency>

          第二步,創(chuàng)建真正的定時任務(wù)執(zhí)行類,該類繼承QuartzJobBean

          public class QuartzTestJob extends QuartzJobBean {
              @Override
              protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                  String userName = (String) context.getJobDetail().getJobDataMap().get("userName");
                  System.out.println("userName:" + userName);
              }
          }

          第三步,創(chuàng)建調(diào)度程序JobDetail和調(diào)度器Trigger

          @Configuration
          public class QuartzConfig {
              @Value("${sue.spring.quartz.cron}")
              private String testCron;

              /**
               * 創(chuàng)建定時任務(wù)
               */

              @Bean
              public JobDetail quartzTestDetail() {
                  JobDetail jobDetail = JobBuilder.newJob(QuartzTestJob.class)
                          .withIdentity("quartzTestDetail", "QUARTZ_TEST")
                          .usingJobData("userName", "susan")
                          .storeDurably()
                          .build()
          ;
                  return jobDetail;
              }

              /**
               * 創(chuàng)建觸發(fā)器
               */

              @Bean
              public Trigger quartzTestJobTrigger() {
                  //每隔5秒執(zhí)行一次
                  CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(testCron);

                  //創(chuàng)建觸發(fā)器
                  Trigger trigger = TriggerBuilder.newTrigger()
                          .forJob(quartzTestDetail())
                          .withIdentity("quartzTestJobTrigger""QUARTZ_TEST_JOB_TRIGGER")
                          .withSchedule(cronScheduleBuilder)
                          .build();
                  return trigger;
              }
          }

          第四步,在applicationContext.properties文件中配置參數(shù):

          sue.spring.quartz.cron=*/5 * * * * ?

          這樣就能每隔5秒執(zhí)行一次QuartzTestJob類的executeInternal方法了。

          CronTrigger配置格式:

          [秒] [分] [小時] [日] [月] [周] [年]

          spring quartzspring taskcron表達式規(guī)則基本一致,只是spring4以上的版本去掉了后面的,而quartzCronTrigger是非必填的,這里我就不做過多介紹了。

          使用spring quartz的優(yōu)缺點:

          • 優(yōu)點:默認是多線程異步執(zhí)行,單個任務(wù)時,在上一個調(diào)度未完成時,下一個調(diào)度時間到時,會另起一個線程開始新的調(diào)度,多個任務(wù)之間互不影響。支持復雜的cron表達式,它能被集群實例化,支持分布式部署。

          • 缺點:相對于spring task實現(xiàn)定時任務(wù)成本更高,需要手動配置QuartzJobBeanJobDetailTrigger等。需要引入了第三方的quartz包,有一定的學習成本。不支持并行調(diào)度,不支持失敗處理策略和動態(tài)分片的策略等。

          四. 分布式定時任務(wù)

          1.xxl-job

          xxl-job是大眾點評(許雪里)開發(fā)的一個分布式任務(wù)調(diào)度平臺,其核心設(shè)計目標是開發(fā)迅速、學習簡單、輕量級、易擴展。現(xiàn)已開放源代碼并接入多家公司線上產(chǎn)品線,開箱即用。

          xxl-job框架對quartz進行了擴展,使用mysql數(shù)據(jù)庫存儲數(shù)據(jù),并且內(nèi)置jetty作為RPC服務(wù)調(diào)用。

          主要特點如下:

          1. 有界面維護定時任務(wù)和觸發(fā)規(guī)則,非常容易管理。
          2. 能動態(tài)啟動或停止任務(wù)
          3. 支持彈性擴容縮容
          4. 支持任務(wù)失敗報警
          5. 支持動態(tài)分片
          6. 支持故障轉(zhuǎn)移
          7. Rolling實時日志
          8. 支持用戶和權(quán)限管理

          管理界面:

          整體架構(gòu)圖如下:

          使用quartz架構(gòu)圖如下:

          項目實戰(zhàn)

          xxl-admin管理后臺部署和mysql腳本執(zhí)行等這些前期準備工作,我就不過多介紹了,有需求的朋友可以找我私聊,這些更偏向于運維的事情。

          假設(shè)前期工作已經(jīng)OK了,接下來我們需要:

          第一步,在pom.xml文件中引入xxl-job相關(guān)依賴。

          <dependency>
             <groupId>com.xuxueli</groupId>
             <artifactId>xxl-job-core</artifactId>
          </dependency>

          第二步,在applicationContext.properties文件中配置參數(shù):

          xxl.job.admin.address: http://localhost:8088/xxl-job-admin/
          xxl.job.executor.appname: xxl-job-executor-sample
          xxl.job.executor.port: 8888
          xxl.job.executor.logpath: /data/applogs/xxl-job/

          第三步,創(chuàng)建HelloJobHandler類繼承IJobHandler類:

          @JobHandler(value = "helloJobHandler")
          @Component
          public class HelloJobHandler extends IJobHandler {

              @Override
              public ReturnT<String> execute(String param) {
                  System.out.println("XXL-JOB, Hello World.");
                  return SUCCESS;
              }
          }

          這樣定時任務(wù)就配置好了。

          建議把定時任務(wù)單獨部署到另外一個服務(wù)中,跟api服務(wù)分開。根據(jù)我以往的經(jīng)驗,job大部分情況下,會對數(shù)據(jù)做批量操作,如果操作的數(shù)據(jù)量太大,可能會對服務(wù)的內(nèi)存和cpu資源造成一定的影響。

          使用xxl-job的優(yōu)缺點:

          • 優(yōu)點:有界面管理定時任務(wù),支持彈性擴容縮容、動態(tài)分片、故障轉(zhuǎn)移、失敗報警等功能。它的功能非常強大,很多大廠在用,可以滿足絕大多數(shù)業(yè)務(wù)場景。

          • 缺點:和quartz一樣,通過數(shù)據(jù)庫分布式鎖,來控制任務(wù)不能重復執(zhí)行。在任務(wù)非常多的情況下,有一些性能問題。

          2.elastic-job

          elastic-job是當當網(wǎng)開發(fā)的彈性分布式任務(wù)調(diào)度系統(tǒng),功能豐富強大,采用zookeeper實現(xiàn)分布式協(xié)調(diào),實現(xiàn)任務(wù)高可用以及分片。它是專門為高并發(fā)和復雜業(yè)務(wù)場景開發(fā)。

          elastic-job目前是apacheshardingsphere項目下的一個子項目,官網(wǎng)地址:http://shardingsphere.apache.org/elasticjob/。

          elastic-job在2.x之后,出了兩個產(chǎn)品線:Elastic-Job-LiteElastic-Job-Cloud,而我們一般使用Elastic-Job-Lite就能夠滿足需求。Elastic-Job-Lite定位為輕量級無中心化解決方案,使用jar包的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù),外部僅依賴于Zookeeper。。

          主要特點如下:

          • 分布式調(diào)度協(xié)調(diào)
          • 彈性擴容縮容
          • 失效轉(zhuǎn)移
          • 錯過執(zhí)行作業(yè)重觸發(fā)
          • 作業(yè)分片一致性,保證同一分片在分布式環(huán)境中僅一個執(zhí)行實例
          • 自診斷并修復分布式不穩(wěn)定造成的問題
          • 支持并行調(diào)度

          整體架構(gòu)圖:

          項目實戰(zhàn)

          第一步,在pom.xml文件中引入elastic-job相關(guān)依賴。

          <dependency>
              <groupId>com.dangdang</groupId>
              <artifactId>elastic-job-lite-core</artifactId>
          </dependency>
          <dependency>
              <groupId>com.dangdang</groupId>
              <artifactId>elastic-job-lite-spring</artifactId>
          </dependency>

          第二步,增加ZKConfig類,配置zookeeper

          @Configuration
          @ConditionalOnExpression("'${zk.serverList}'.length() > 0")
          public class ZKConfig {

              @Bean
              public ZookeeperRegistryCenter registry(@Value("${zk.serverList}") String serverList,
                                                       @Value("${zk.namespace}") String namespace) 
          {
                  return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList, namespace));
              }

          }

          第三步,定義一個類實現(xiàn)SimpleJob接口:

          public class TestJob implements SimpleJob {

              @Override
              public void execute(ShardingContext shardingContext){
                  System.out.println("ShardingTotalCount:"+shardingContext.getShardingTotalCount());
                  System.out.println("ShardingItem:"+shardingContext.getShardingItem());
              }
          }

          第四步,增加JobConfig配置任務(wù):

          @Configuration
          public class JobConfig {
              @Value("${sue.spring.elatisc.cron}")
              private String testCron;
              @Value("${sue.spring.elatisc.itemParameters}")
              private  String shardingItemParameters;
              @Value("${sue.spring.elatisc.jobParameters}")
              private String jobParameters =;
              @Value("${sue.spring.elatisc.shardingTotalCount}")
              private int shardingTotalCount;
              
              @Autowired
              private ZookeeperRegistryCenter registryCenter;

              @Bean
              public SimpleJob testJob() {
                  return new TestJob();
              }

              @Bean
              public JobScheduler simpleJobScheduler(final SimpleJob simpleJob) {
                  return new SpringJobScheduler(simpleJob, registryCenter, getConfiguration(simpleJob.getClass(),
                          cron, shardingTotalCount, shardingItemParameters, jobParameters));
              }

              private geConfiguration getConfiguration(Class<? extends SimpleJob> jobClass,String cron,int shardingTotalCount,String shardingItemParameters,String jobParameters) {
                  JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(jobClass.getName(), testCron, shardingTotalCount).
                          shardingItemParameters(shardingItemParameters).jobParameter(jobParameters).build();
                  SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, jobClass.getCanonicalName());
                  LiteJobConfiguration jobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();
                  return jobConfig;
              }
          }

          其中:

          • cron:cron表達式,定義觸發(fā)規(guī)則。
          • shardingTotalCount:定義作業(yè)分片總數(shù)
          • shardingItemParameters:定義分配項參數(shù),一般用分片序列號和參數(shù)用等號分隔,多個鍵值對用逗號分隔,分片序列號從0開始,不可大于或等于作業(yè)分片總數(shù)。
          • jobParameters:作業(yè)自定義參數(shù)

          第五步,在applicationContext.properties文件中配置參數(shù):

          spring.application.name=elasticjobDemo
          zk.serverList=localhost:2181
          zk.namespace=elasticjobDemo
          sue.spring.elatisc.cron=0/5 * * * * ?
          sue.spring.elatisc.itemParameters=0=A,1=B,2=C,3=D
          sue.spring.elatisc.jobParameters=test
          sue.spring.elatisc.shardingTotalCount=4

          這樣定時任務(wù)就配置好了,創(chuàng)建定時任務(wù)的步驟,相對于xxl-job來說要繁瑣一些。

          使用elastic-job的優(yōu)缺點:

          • 優(yōu)點:支持分布式調(diào)度協(xié)調(diào),支持分片,適合高并發(fā),和一些業(yè)務(wù)相對來說較復雜的場景。

          • 缺點:需要依賴于zookeeper,實現(xiàn)定時任務(wù)相對于xxl-job要復雜一些,要對分片規(guī)則非常熟悉。

          3.其他分布式定時任務(wù)


          1. Saturn

          Saturn是唯品會開源的一個分布式任務(wù)調(diào)度平臺。取代傳統(tǒng)的Linux Cron/Spring Batch Job的方式,做到全域統(tǒng)一配置,統(tǒng)一監(jiān)控,任務(wù)高可用以及分片并發(fā)處理。


          Saturn是在當當開源的Elastic-Job基礎(chǔ)上,結(jié)合各方需求和我們的實踐見解改良而成。使用案例:唯品會、酷狗音樂、新網(wǎng)銀行、海融易、航美在線、量富征信等。 


          github地址:https://github.com/vipshop/Saturn/

          2. TBSchedule

           TBSchedule是阿里開發(fā)的一款分布式任務(wù)調(diào)度平臺,旨在將調(diào)度作業(yè)從業(yè)務(wù)系統(tǒng)中分離出來,降低或者是消除和業(yè)務(wù)系統(tǒng)的耦合度,進行高效異步任務(wù)處理。


          目前被廣泛應(yīng)用在阿里巴巴、淘寶、支付寶、京東、聚美、汽車之家、國美等很多互聯(lián)網(wǎng)企業(yè)的流程調(diào)度系統(tǒng)中。


          github地址:https://github.com/taobao/TBSchedule


          老實說優(yōu)秀的定時任務(wù)還是挺多的,不是說哪種定時任務(wù)牛逼我們就一定要用哪種,而是要根據(jù)實際業(yè)務(wù)需求選擇。每種定時任務(wù)都有優(yōu)缺點,合理選擇既能滿足業(yè)務(wù)需求,又能避免資源浪費,才是上上策。當然在實際的業(yè)務(wù)場景,通常會多種定時任務(wù)一起配合使用。


          順便說一句,歡迎親愛的小伙伴們,找我一起聊聊:你用過哪些定時任務(wù),遇到過哪些問題,以及如何解決問題的。如果有相關(guān)問題也可以問我。


          希望我們能夠共同進步,一起成長。


          最后說一句(求關(guān)注,別白嫖我)

          如果這篇文章對您有所幫助,或者有所啟發(fā)的話,幫忙掃描下發(fā)二維碼關(guān)注一下,您的支持是我堅持寫作最大的動力。

          求一鍵三連:點贊、轉(zhuǎn)發(fā)、在看。

          關(guān)注公眾號:【蘇三說技術(shù)】,在公眾號中回復:面試、代碼神器、開發(fā)手冊、時間管理有超贊的粉絲福利,另外回復:加群,可以跟很多BAT大廠的前輩交流和學習。

           個人公眾號

           個人微信



          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  chaopeng超碰永久 | 影音先锋三级理伦电影 | 人人色人人操人人 | 亚洲精品国产精品国自产网站 | 8050午夜无码一区二区三区 |