1. 程式人生 > >專案中使用Quartz叢集分享--轉載

專案中使用Quartz叢集分享--轉載

原文:http://hot66hot.iteye.com/blog/1726143

在公司分享了Quartz,釋出出來,希望大家討論補充. 

CRM使用Quartz叢集分享 
一:CRM對定時任務的依賴與問題 
二:什麼是quartz,如何使用,叢集,優化 
三:CRM中quartz與Spring結合使用 

1:CRM對定時任務的依賴與問題 
1)依賴 
(1)每天晚上的定時任務,通過sql指令碼 + crontab方式執行 

  1. #crm  
  2. 0 2 * * * /opt/***/javafiles/***/shell/***_daily_stat.sql  
  3. 30 7 * * * /opt/***/javafiles/***/shell/***_data_fix  
  4. 30 0 * * * /opt/***/javafiles/***/shell/***_sync_log  
  5. 0 1 * * * /opt/***/javafiles/***/shell/***_clear_log  
  6. 20 8 * * * /opt/***/javafiles/***/shell/***_daily >> /var/***/logs/***_daily.log 2>&1  
  7. 40 1 * * * /opt/***/javafiles/***/shell/***_sync_account2  
  8. 0 2 * * 1 /opt/***/javafiles/***/shell/***_weekly >> /var/***/logs/***_weekly.log 2>&1  


存在的問題:當需要跨庫或許資料的,sql無能為力,引入許多中間表,完成複雜統計需求。大範圍對線上熱表掃描,造成鎖表,延遲嚴重 
(2)使用python(多資料來源) + SQL的方式 

  1. def connectCRM():  
  2.     return MySQLdb.Connection("localhost", "***", "***", "***", 3306, charset="utf8")  
  3. def connectTemp():  
  4.     return MySQLdb.Connection("localhost", "***", "***",  "***", 3306, charset="utf8")  
  5. def connectOA():  
  6.     return MySQLdb.Connection("localhost", "***", "***",  "***", 3306, charset="utf8")  
  7. def connectCore():  
  8.     return MySQLdb.Connection("localhost", "***", "***",  "***", 3306, charset="utf8")  
  9. def connectCT():  
  10.     return MySQLdb.Connection("localhost", "***", "***", "***", 3306, charset="utf8")  



存在的問題:直接訪問資料,需要理解各系統的資料結構,無法滿足動態任務問題,各系統業務介面沒有重用 

(3)使用spring + JDK timer方式呼叫介面完成定時任務 

  1. <bean id="accountStatusTaskScanner"  class="***.impl.AccountStatusTaskScanner" />  
  2.     <task:scheduler id="taskScheduler" pool-size="5" />  
  3.     <task:scheduled-tasks scheduler="taskScheduler">  
  4.     <task:scheduled ref="accountStatusTaskScanner" method="execute" cron="0 0 1 * * ?" />  
  5. </task:scheduled-tasks>  


使用寫死伺服器Host(srv23)的方式,控制只在一臺伺服器上執行task 

  1. public abstract class SingletonServerTaskScanner implements TaskScanner {  
  2.     private final Logger logger = LoggerFactory.getLogger(SingletonServerTaskScanner.class);  
  3.     @Override  
  4.     public void execute() {  
  5.         String hostname = "";  
  6.         try {  
  7.             hostname = InetAddress.getLocalHost().getHostName();  
  8.         } catch (UnknownHostException e) {  
  9.             logger.error(e.getMessage(), e);  
  10.         }  
  11.         //判斷是否為當前可執行伺服器  
  12.         if (ConfigUtil.getValueByKey("core.scan.server").equals(hostname)) {  
  13.             doScan();  
  14.         }  
  15.     }  
  16.     public abstract void doScan();  
  17. }  



//對於srv23的重啟,儲存在記憶體中的任務將丟失,每次重啟srv23重新生成定時任務 

  1. public class CrmInitializer implements InitializingBean {  
  2.     private Logger logger = LoggerFactory.getLogger(CrmInitializer.class);  
  3.     @Override  
  4.     public void afterPropertiesSet() throws Exception {  
  5.         // 掃描商家狀態,建立定時任務  
  6.         logger.info("掃描商家狀態,建立定時任務");  
  7.         accountStatusTaskScanner.execute();  
  8.         // 掃描N天未拜訪商家,建立定時任務  
  9.         logger.info("掃描N天未拜訪商家,建立定時任務");  
  10.         nDaysActivityScanner.execute();  
  11.     }  
  12. }  
  1. //通過呼叫srv23的特定URL的方式,動態指定任務(如取消N天未拜訪,私海進保護期,保護期進公海等)  
  2. public class SingletonServerTaskController {  
  3.         @Resource  
  4.         private AccountService accountService;  
  5.         @RequestMapping(value = "/reschedule")  
  6.         public @ResponseBody  
  7.             String checkAndRescheduleAccount(Integer accountId) {  
  8.             logger.debug("reschedule task for accountId:" + accountId);  
  9.             if (isCurrentServer()) {  
  10.                 accountService.checkAndRescheduleAccount(Arrays.asList(accountId));  
  11.             }  
  12.             return "ok";  
  13.         }  
  14.     private boolean isCurrentServer() {  
  15.         String hostname = "";  
  16.         try {  
  17.             hostname = InetAddress.getLocalHost().getHostName();  
  18.         } catch (UnknownHostException e) {  
  19.             logger.error(e.getMessage(), e);  
  20.         }  
  21.         if (ConfigUtil.getValueByKey("core.scan.server").equals(hostname)) {  
  22.             return true;  
  23.         } else {  
  24.             return false;  
  25.         }  
  26.     }  
  27. }  


存在的問題:實現步驟複雜,分散,任務排程不能恢復,嚴重依賴於srv23,回撥URL時可能失敗等情況。 
CRM定時任務走過了很多彎路: 
定時任務多種實現方式,使配置和程式碼分散在多處,難以維護和監控 
任務執行過程沒有保證,沒有錯誤恢復 
任務執行異常沒有反饋(郵件) 
沒有叢集支援 
CRM需要分散式的任務排程框架,統一解決問題. 
JAVA可以使用的任務排程框架:Quartz , Jcrontab , cron4j , taobao-pamirs-schedule 
為什麼選擇Quartz: 
1)資歷夠老,創立於1998年,比struts1還早,但是一直在更新(27 April 2012: Quartz 2.1.5 Released),文件齊全. 
2)完全由Java寫成,設計用於J2SE和J2EE應用.方便整合:JVM,RMI. 
3)設計清晰簡單:核心概念scheduler,trigger,job,jobDetail,listener,calendar 
4)支援叢集:org.quartz.jobStore.isClustered 
5)支援任務恢復:requestsRecovery 

從http://www.quartz-scheduler.org 獲取最新Quartz 
1)學習Quartz 

 
圖1 介紹了quartz關鍵的元件和簡單流程 

(1)Quartz 的目錄結構和內容 

docs/api                                      Quartz 框架的JavaDoc Api 說明文件 
docs/dbTables                            建立 Quartz 的資料庫物件的指令碼 
docs/wikidocs                             Quartz 的幫助檔案,點選 index.html 開始檢視 
Examples                                    多方面使用 Quartz 的例子Lib Quartz 使用到的第三方包 
src/java/org/quartz                      使用 Quartz 的客戶端程式原始碼,公有 API 
src/java/org/quartz/core              使用 Quartz 的服務端程式原始碼,私有 API 
src/java/org/quartz/simpl            Quartz 提供的不衣賴於第三方產品的簡單實現 
src/java/org/quartz/impl              依賴於第三方產品的支援模組的實現 
src/java/org/quartz/utils              整個框架要用到的輔助類和工具元件 
src/jboss                                     提供了特定於 JBoss 特性的原始碼 
src/oracle                                   提供了特定於 Oracle 特性的原始碼 
src/weblogic                              提供了特定於 WebLogic 特性的原始碼 

Quartz 框架包含許多的類和介面,它們分佈在大概 11 個包中。多數所要使用到的類或介面放置在 org.quartz 包中。這個包含蓋了 Quartz 框架的公有 API. 

(2)Quartz核心介面 Scheduler 


圖2 
Scheduler 是 Quartz 的主要 API。與Quartz大部分互動是發生於 Scheduler 之上的。客服端與Scheduler 互動是通過org.quartz.Scheduler介面。 
Scheduler的實現:對方法呼叫會傳遞到 QuartzScheduler 例項上。QuartzScheduler 對於客戶端是不可見的,並且也不存在與此例項的直接互動。 

 

圖3 

建立Scheduler 
Quartz 框架提供了 org.quartz.SchedulerFactory 介面。 
SchedulerFactory 例項就是用來產生 Scheduler 例項的。當 Scheduler 例項被建立之後,就會存到一個倉庫中(org.quartz.impl.SchedulerRepository). 
Scheduler 工廠分別是 org.quartz.impl.DirectSchedulerFactory 和 org.quartz.impl.StdSchedulerFactory 
DirectSchedulerFactory 是為精細化控制 Scheduler 例項產生的工廠類,一般不用,不過有利於理解quartz內部元件。 

  1. -- 最簡單  
  2. public void createScheduler(ThreadPool threadPool, JobStore jobStore);  
  3. -- 最複雜  
  4. public void createScheduler(String schedulerName, String schedulerInstanceId,ThreadPool threadPool, JobStore jobStore, String rmiRegistryHost, int rmiRegistryPort);  
  1. public scheduler createScheduler(){  
  2.  DirectSchedulerFactory factory=DirectSchedulerFactory.getInstance();  
  3.  try {  
  4.     //建立執行緒池  
  5.     SimpleThreadPool threadPool = new SimpleThreadPool(10, Thread.NORM_PRIORITY);  
  6.     threadPool.initialize();  
  7.     //建立job儲存類  
  8.     JobStoreTX jdbcJobStore = new JobStoreTX();  
  9.     jdbcJobStore.setDataSource("someDatasource");  
  10.         jdbcJobStore.setPostgresStyleBlobs(true);  
  11.         jdbcJobStore.setTablePrefix("QRTZ_");  
  12.         jdbcJobStore.setInstanceId("My Instance");  
  13.     logger.info("Scheduler starting up...");  
  14.     factory.createScheduler(threadPool,jdbcJobStore);  
  15.     // Get a scheduler from the factory  
  16.         Scheduler scheduler = factory.getScheduler();  
  17.     // 必須啟動scheduler  
  18.         scheduler.start();  
  19.         return scheduler;  
  20.     }  
  21.         return null;  
  22. }  



org.quartz.impl.StdSchedulerFactory 依賴於屬性類(Properties)決定如何生產 Scheduler 例項 

通過載入屬性檔案,Properties 提供啟動引數: 

  1. public scheduler createScheduler(){  
  2.     // Create an instance of the factory  
  3.     StdSchedulerFactory factory = new StdSchedulerFactory();  
  4.     // Create the properties to configure the factory  
  5.     Properties props = new Properties();  
  6.     // required to supply threadpool class and num of threads  
  7.     props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,"org.quartz.simpl.SimpleThreadPool");  
  8.     props.put("org.quartz.threadPool.threadCount", "10");  
  9.     try {  
  10.         

    相關推薦

    專案使用Quartz叢集分享--轉載

    原文:http://hot66hot.iteye.com/blog/1726143 在公司分享了Quartz,釋出出來,希望大家討論補充.  CRM使用Quartz叢集分享  一:CRM對定時任務的依賴與問題  二:什麼是quartz,如何使用,叢集,

    spring專案quartz的job類不能自動注入bean的問題

    在execute()方法中加入以下紅色部分程式碼://定時清除失效商品public class ClearInvalidGoodsJob implements Job {@Autowiredprivate GoodsInfoService goodsInfoservice;@

    vue專案如何使用百度三方分享

    百度三方分享 今天專案中用到分享功能,正好是vue專案,本來想著在網上找下操作教程,結果找了半天,發現也沒幾個能用的,還一個比一個能吹,步驟沒一點思緒,就一氣之下自己著手摸索出來一個,還沒寫樣式,但功能已經能用了。 效果圖如下: 步驟 在百度分享官網下載程式碼:ht

    07-專案以經典的3節點方式部署哨兵叢集

    1、哨兵的配置檔案 sentinel.conf 最小的配置 每一個哨兵都可以去監控多個maser-slaves的主從架構 因為可能你的公司裡,為不同的專案,部署了多個master-slaves的redis主從叢集 相同的一套哨兵叢集,就可以去監控不同的

    專案使用redis單機版和叢集

    redis搭建請看上一篇文章新增jedis依賴: <!-- Redis客戶端 --> <dependency> <groupId>redis.clients</groupId> &l

    vue專案分享到朋友圈,呼叫微信介面

    雖然微信提供了jssdk,不代表可以點選按鈕進行分享到朋友圈,是需要微信自帶的瀏覽器右上角進行分享。手機瀏覽器需要瀏覽器支援分享到朋友圈的分享機制。 微信jssdk地址: https://mp.weixin.qq.com/wiki?action=doc&id=mp1421141115&t=

    Java EE專案的異常處理 (實在寫的太好了,導致我非法轉載!!!)

    為什麼要在J2EE專案中談異常處理呢?可能許多java初學者都想說:“異常處理不就是try….catch…finally嗎?這誰都會啊!”。筆者在初學java時也是這樣認為的。如何在一個多層的j2ee專案中定義相應的異常類?在專案中的每一層如何進行異常處理?異常何時被丟擲

    Storm和Zookeeper叢集搭建及在java專案的使用

    上一篇: 介紹了分散式Zookeeper叢集的搭建和Kafka叢集的搭建,接下來學習一下Storm叢集的搭建。 實驗環境 Cent OS 6.9 apache-storm-1.1.0 三臺伺服器虛擬機器:192.168.1.129、192.1

    Springboot quartz叢集(1) — 專案跑起來

    開發工具: IDEA 2017.1.5 Maven專案管理 1. 新建springboot模組 模組名稱:cnlm-springboot-quartz 2. 重新命名springboot啟動類為Application @Spr

    Intellij IDEA 如何檢視maven專案所有jar包的依賴關係圖(轉載

    Intellij IDEA 中如何檢視maven專案中所有jar包的依賴關係圖 2017年04月05日 10:53:13 李學凱 閱讀數:104997更多 所屬專欄: Intellij Idea

    C++知識分享:C++專案的extern "C" {}

    引言 在用C++的專案原始碼中,經常會不可避免的會看到下面的程式碼: #ifdef __cplusplus extern "C" { #endif /*...*/ #ifdef __cplusplus } #endif它到底有什麼用呢,你知道嗎

    分享我們專案基於EF事務機制的架構

    寫在前面: 1. 本文中單元測試用到的資料庫,在執行測試之前,會被清空,即使用空資料庫。 2. 本文中的單元測試都是正確通過的。 要理解EF的事務機制,首先要理解這2個類:TransactionScope和DbContext。 DbContext是我們的資料庫,通常我們會建一個類MyProjectDb

    spring整合quartz定時器的專案,如何關閉不斷輸出的batch acquisition of 0 triggers ?

    不斷輸出的batch acquisition of 0 triggers太鬧心了,嚴重影響了除錯效率,不能忍,經過查閱資料得出關閉方法。希望幫助更多的小夥伴。解決方法:在pom.xml中看看使用的是哪個

    Quartz(06) quartz整合到web專案

    上一章節地址Quartz(05) job 的持久化 在開發中我們往往需要把Quartz專案整合到web專案中.本文采用最原始的方式來整合,不涉及到Spring. Quartz+Spring +Web的整合將放在後面講解. 我們要達到的效果就是,已啟動web

    quartz整合到web專案

    上一章節地址Quartz(05) job 的持久化在開發中我們往往需要把Quartz專案整合到web專案中.本文采用最原始的方式來整合,不涉及到Spring. Quartz+Spring +Web的整合將放在後面講解.我們要達到的效果就是,已啟動web專案,我們的schedu

    分享我在前後端分離專案Gitlab-CI的經驗

    長話短說,今天分享我為`前後端分離專案`搭建Gitlab CI/CD流程的一些額外經驗。 ### Before Gitlab-ci是Gitlab提供的CI/CD特性,結合Gitlab簡單友好的配置介面,能愉悅的在Gitlab介面檢視管道執行流程,並自然流暢的推動敏捷開發流程。 Gitlab-CI/CD的

    SpringQuartz的配置

    str ask doc nbsp 任務調度 trigge -- enc object 軟件152蘇銳 Quartz是一個強大的企業級任務調度框架,Spring中繼承並簡化了Quartz,下面就看看在Spring中怎樣配置Quartz:首先我們來寫一個被調度的類: packa

    GC調優在Spark應用的實踐(轉載

    avg fix 時也 net aso 會有 介紹 完整 頻繁 Spark是時下非常熱門的大數據計算框架,以其卓越的性能優勢、獨特的架構、易用的用戶接口和豐富的分析計算庫,正在工業界獲得越來越廣泛的應用。與Hadoop、HBase生態圈的眾多項目一樣,Spark的運行離不開J

    我做國家自科基金委評委的那幾年-工作經歷分享-轉載

    會有 也會 之間 渴望 由於 還需 那是 實驗 理解 我做國家自科基金委評委的那幾年--工作經歷分享【轉載】 壹學者將連續轉載一位曾經在國家自然科學基金委任流動編制項目主任的學者發布於科學網的長篇博文。 在該博文中,作者會陸續介紹與解釋基金項目評審中的各個環節與部

    非廣告:《工作軟件分享》--PDF/EXCEL/WORD優化、壓縮處理軟件

    PDF 壓縮 分享原因:工作中通過一體式打印機掃描紙質文件後產生的 PDF 實在是太大,不可以在通過郵箱正常的發送出去。 為了解決這個頭痛與苦惱的問題,一直以來都在麻煩度娘。 測試過的方法: 1、pdf打印機再打印。 >>>>>>使用cutpdf打印機再打印後,文