THINKING MEGANE

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-randomSecureRandomをmrubyで使えるようにするためにつくったmrbgemです。SidekiqのJIDを算出するために利用しています。ランダムデバイスとして /dev/urandom しか対応していないため Windows環境だと動きません。PullRequestお待ちしております。

まとめ

こんな感じでmrubyからSidekiqと連携できるようにしてみました。シンプルなジョブキューであればRails使わずにngx_mrubyとRedis、Rubyだけでつくれてしまうので便利では〜と個人的には思っています。

あわせて、今後、mruby使った動的なフロントサーバーがサービスのどの要件までを担当すべきかといった構成は常に考えていかなければいけないだろうなあとも感じています。適材適所それぞれの利点を最大限に活かせる構成を検討したいところ。

このエントリーをはてなブックマークに追加