delay異步處理

使用Delayed job處理Rails中的異步任務

    Rails cast上有關於介紹Delayed job的使用範例的:使用delayed job處理一個異步發送郵件的任務。我沒仔細看。然後自己弄了起來。記錄過程如下,希望給後來者提供一些幫助。

    首先介紹下應用場景:在WEB應用中,系統執行某些任務時,可能執行結果比較長,並且不需要及時把結果反饋給用戶。這樣我們就需要將這些處理時間長的請求剝離成異步處理,及時響應頁面的請求。比如Rails cast中示例的發郵件。可能發郵件需要2到10秒鐘不等。這個請求如果採用同步處理,會讓用戶覺得卡了一下的感覺,體驗不好。如果採用異步處理,只需要記錄需要處理這個任務,然後將任務記錄在某個地方,再由後臺程序去調度執行這些任務,這樣就可以在極短時間(如果其他代碼沒有問題)內給用戶反饋信息,這樣體驗就會好很多。

    我的應用場景是:一個用例在修改名稱後,需要將名稱同步到腳本相關的Excel中。修改Excel的過程比較長,至少會有3秒以上。這樣就需要將這個修改異步出去。我的環境是ruby ee + Rails 3 + Mysql。

    在github上搜索delayed job。可以得到好多個分支的delayed job插件。collectiveidea 分支的不錯,可以自動建立migration和script任務。

     原理如下:在Object對象上擴展了一個delay方法。如果遇到任何需要異步處理的函數,就使用對象.delay.方法名。比如正常代碼爲:Mail.send_mail(@mail) ,異步處理即爲:Mail.delay.send_mail(@mail)。delay函數中利用ruby的動態性,即將send_mail方法異步調用:先寫入到數據庫的表delayed_jobs,生成一條記錄,worker進程會每隔5秒去檢查一下數據庫這張表的記錄,如果有記錄就去讀取出來處理掉,然後再刪除記錄。有點像消息隊列的處理機制。廢話完畢,開幹~~~

    1、在Gemfile裏面配置:gem 'delayed job'。然後在工程目錄下執行:sudo bundle install

    2、執行ruby script/generate delayed_job 。會創建Model和Migration。執行rake db:migration即可建立數據庫表。

    3、啓動worker:ruby scrpt/delayed_job。這個進程就是去定時讀取數據庫任務的。

    4、在需要處理的函數上都加上.delay.方法名。

    大功告成。

    有個小問題需要注意:Rails中啓動應用會有不同的環境,爲了讓delayed_job這個worker找到正確的數據庫,需要設置系統的環境變量,執行:export RAILS_ENV=online_production 。這樣再啓動delayed job的worker進程時,就會去讀取online_production對應的數據庫。

      delayed_job值得提及的特性就是自動重試功能。如果一個方法拋出了異常,這個異常會被捕獲,之後這個方法將會重新運行。這個過程最多重複25次,次數越多重試的時間間隔就越長。

     在分佈式中,worker進程只需要啓動一個即可。不需要每個機器都啓動worker去讀取數據庫的任務去執行。在異步任務不是太多時,一個進程完全夠用。並且,時間瓶頸也並非在一個進程還是在兩個進程上,主要還是在處理異步任務的代碼上。另外,需要說明的是,worker啓動時可以指定多個實例。還有其他一些參數,運行:ruby script/delayed_job可以看到幫助。

轉載自:http://www.myexception.cn/ai/844431.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章