Active Job 的佈署實例

當我們在 Web 處理 Request 的執行緒做一些消耗性能但是又不緊急的工作,流量大時不免會變成系統效能的瓶頸。

Async => 非同步的設計在這時候可以幫我們降低同一個執行緒要處理的工作消耗,可以用來處理類似發信,寫檔案,緩慢寫入讀取資料的事情。

在 Rails 要做到很簡單,Rails 有 Active Job 可以搭配許多 Queue framework,這邊我用的 Resque 就是其中之一。設定並不困難,安裝了 gem 然後在 #{env}.rb 設定

config.active_job.queue_adapter = :resque
config.active_job.queue_name_prefix  = "app_#{Rails.env}"

這邊要說的是…部署這些 Job 的方式。

之前有提到的專案應用上,我使用的系統是 Ubuntu 16。Rails 的 Application 裡用的是 foreman 來管理啟動 unicorn server。

web: bundle exec unicorn -c ./config/unicorn.rb

Worker 也可以這樣使用。在我們佈署到上線的環境時,我們會需要把這些 Worker 的執行程式包裝成服務來啟動。醬可以藉由設定讓他在 Server 重啟之後自己繼續執行。

Woker 的 Procfile 會像這樣:

mailer: rake environment resque:work QUEUE=store_${RAILS_ENV}_mailers
logger: rake environment resque:work QUEUE=store_${RAILS_ENV}_logger
filegen: rake environment resque:work QUEUE=store_${RAILS_ENV}_file_generation

Foreman 可以幫我們做到這點。它提供了許多匯出成系統服務的指令。我使用的指令如下:

$ sudo foreman export systemd --env .production-env --app storeworkers --user store /etc/systemd/system

這個指令會依照當下執行目錄的 Procfile 加上 --env 指定的環境變數來產生服務設定檔,放在指定的 /etc/systemd/system 裡。

產生的 /etc/systemd/system/storeworkers.target 會包含 Procfile 指定的所有工作,而每一個 Procfile 指定的工作內容將會被定義匯出在 /etc/systemd/system 裡。

匯出後我們可以透過 systemctl 來設定。

$ sudo systemctl [start|restart|enable] storeworkers.target

設定為 enable 後將可以在系統啟動後一併執行服務。

status 則可以查看該 worker 的最近幾筆紀錄

sudo systemctl status storeworkers.target

● storeworker.target
   Loaded: loaded (/etc/systemd/system/storeworkers.target; enabled; vendor preset: enabled)
   Active: active since Thu 2017-06-29 02:59:04 UTC; 20min ago

Jun 29 02:59:04 storeworkers systemd[1]: Stopped target storeworkers.target.
Jun 29 02:59:04 storeworkers systemd[1]: Stopping storeworkers.target.
Jun 29 02:59:04 storeworkers systemd[1]: Reached target storeworkers.target.