mrubyからSidekiqに非同期ジョブを登録するmrbgemをつくった
ngx_mrubyでHTTPリクエストに対して非同期処理をしたかったので、mruby-sidekiq-client
という mrbgem をつくりました。
mrubyからSidekiqのジョブ形式でRedisに非同期ジョブを登録し、別途用意したSidekiqのサーバーが登録されたジョブを捌いていくという方式です。これにより、非同期処理は通常のRailsやCRubyのコードで書くことができ、mruby側の処理はシンプルに保つことができます。
使い方
RailsなどでSidekiqを使っている方にはお馴染みのやり方です。
1. 非同期ジョブにしたいWorkerクラスを定義します
class HardWorker
include Sidekiq::Worker
end
※ perform
メソッドはmruby側では実装する必要はありません。Sidekiqサーバー側のRubyコードに実装してください。
2. 非同期ジョブを登録する処理を定義します。
HardWorker.perform_async('bob', 5)
指定時間後に実行するジョブも登録できます
HardWorker.perform_in(300, 'bob', 5) # 300秒後に実行
mruby側はこれだけです。あとは先ほどのWorkerクラスと同じクラスをSidekiqサーバー側に追加し、performメソッドに非同期ジョブの内容を記述します。
ngx_mrubyで使う
mruby_userdataを使って、リクエストごとにRedis再接続しないようにしておきます。
http {
(snip)
mruby_init_code '
userdata = Userdata.new "redis_data_key"
userdata.redis = Redis.new "localhost", 6379
';
server {
(snip)
location /hello {
mruby_content_handler_code '
userdata = Userdata.new "redis_data_key"
Sidekiq.redis = userdata.redis
class MyWorker; include Sidekiq::Worker; end
(snip)
MyWorker.perform_async(args)
';
}
Sidekiqサーバー
SidekiqサーバーはPlain Rubyの環境でも動作するため、ngx_mrubyとRedis、Rubyだけでシンプルなジョブキューをつくることができます。 手順はこちらを参考にしてください。
インストール
build_config.rb
に以下を記述してください。
conf.gem :github => 'monochromegane/mruby-secure-random'
conf.gem :github => 'monochromegane/mruby-sidekiq-client'
mruby-secure-randomはSecureRandom
をmrubyで使えるようにするためにつくったmrbgemです。SidekiqのJIDを算出するために利用しています。ランダムデバイスとして /dev/urandom
しか対応していないため Windows環境だと動きません。PullRequestお待ちしております。
まとめ
こんな感じでmrubyからSidekiqと連携できるようにしてみました。シンプルなジョブキューであればRails使わずにngx_mrubyとRedis、Rubyだけでつくれてしまうので便利では〜と個人的には思っています。
あわせて、今後、mruby使った動的なフロントサーバーがサービスのどの要件までを担当すべきかといった構成は常に考えていかなければいけないだろうなあとも感じています。適材適所それぞれの利点を最大限に活かせる構成を検討したいところ。