對于Web容器來說,最忌諱應用程序私自啟動線程,自行進行線程調度,像Quartz這種在web容器內部默認就自己啟動了10個線程進行異步job調度的框架本身就是很危險的事情,很容易造成servlet線程資源回收不掉,所以我一向排斥使用quartz。
quartz還有一個問題就是不支持cluster。導致使用quartz的應用都沒有辦法做群集。
那么應該如何正確的使用quartz的同時,又不影響web容器自身的線程調度呢?
辦法就是自己單獨啟動一個Job Server,來quartz跑job,不要部署在web容器中。
其他web節點當需要啟動異步任務的時候,可以通過種種方式(DB, JMS, Web Service, etc)通知Job Server,而Job Server收到這個通知之后,把異步任務加載到自己的任務隊列中去。
其實想改造當前已經集成quartz的web應用也不算困難:
例如可以使用數據庫的表來記錄和維護任務隊列和狀態,把quartz部分完全從web應用中剝離出去,自己寫一個Java Main程序把配置quartz的spring容器跑起來,這樣Job Server就啟動了(注意這個Job Server完全脫離tomcat)。此外這個Main程序應該再啟動一個子線程,定期掃描數據庫的任務隊列表:
有新的任務就加入quartz的任務調度;
把當前任務的執行狀態寫入任務表;
看到刪除任務的表字段狀態以后,刪除相應的任務。
然后web應用去掉quartz部分配置,把原來的調用quartz任務的代碼改寫為讀寫數據庫的任務表,這樣就把job部分完全從web容器剝離掉了,甚至web容器做cluster也沒有問題了,并且多個web節點在同時讀寫任務表的時候,還有數據庫的事務來確保操作的一致性,實在是很棒。
另外還可以單獨做一個job管理界面,可以通過web界面手工添加任務,查看任務狀態,刪除任務等等。