シーエー・アドバンス Advent Calendar 2020 - Qiita 18日目の記事です。
Shoryuken導入の経緯
数万件のCSVデータを登録する機能を作成しましたが、処理に時間がかかってしまい処理が完了する前にタイムアウトしてしまう事象が発生しました。
タイムアウトを延長も検討しましたが付け焼き刃的対応であるため、数万件登録でも対応できるよう非同期処理できる機能が必要でした。
検討した処理の流れは以下となります。
- SPA画面よりCSVをアップロードした際、S3に保存してキューをSQSに登録する
- Workerにてキューを取得しバックグラウンドでS3からCSVをダウンロードしてCSV内のデータをDBに登録する
Shoryukenとは
AWS SQSと連動したActive Job Worker。
sidekiqが有名みたいですが、そちらがRedisをqueueStoreとしているのに対し、ShoryukenはSQSをqueueStoreとしています。
最初Sidekiqの導入を検討しましたが、耐障害性の高いSQSを使用したかったため他にもないと探していた際に目的にあったShoryukenを発見。即導入に至りました。
キューの作成
SQSにあらかじめキューを作成しておきます。
導入
gem 'shoryuken'
bundle install
します
$ bundle install
設定ファイルは以下になります。
1処理の件数が多いため、スレッド数は控えめにしました。
concurrency: 5
delay: 30
require: /usr/src/app/app/workers
pidfile: /usr/src/app/tmp/pids/shoryuken.pid
queues:
- sqs_queue_sample
メッセージを取得するサーバー設定を作成します。
今回、キューの取得のみShoryukenを使用しますが、キュー登録の場合は、configure_client
を定義すると、Shoryuken経由でキューの登録が行えます。
workerはECS fargateでコンテナ作成するため、ログはCloudwatch Logsで確認できるよう標準出力するようにしてます。
Shoryuken.configure_server do |config|
config.sqs_client = Aws::SQS::Client.new(
region: "ap-northeast-1",
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
verify_checksums: false
)
Rails.logger = Shoryuken::Logging.logger
Rails.logger.level = :info
end
Shoryuken::Logging.initialize_logger(STDOUT)
workerのメイン処理を実装します。
キューにメッセージが登録されるとperform
メソッドが実行され、メッセージが受け取れます。
あとは、CSVデータの登録処理を書いていきます。
class doWorker
include Shoryuken::Worker
shoryuken_options queue: 'sqs_queue_sample', auto_delete: true, body_parser: json
def perform(sqs_msg, body)
(ここにworker処理を書く)
end
end
あとは、下記コマンドで起動させればOKです。
コンテナで運用する場合は、dockerfileのCMD
に下記コマンドを追加でworkerとして起動します。
$ bin/bundle exec shoryuken -R -C config/shoryuken.yml
導入後
CSV登録処理をバックグラウンド化したことで、CSVレコード数でタイムアウトせず、
またSQSとShoryukenでスレッド化することで過剰な負荷がかかることがなくなりました。
稼働させて1ヶ月弱ですが、不具合などは発生していません。
gemモジュールを使用することでサクッと実装できました。
開発環境ではSQSの代わりにFakeSQSを実装したかったのですが、時間的都合で見送りとなりました。
開発用SQSキューを作成していますが、料金は発生してしまうので、FakeSQSコンテナで開発を行えるようにするつもりです。