RailsのActiveJobでSidekiqの代わりにSneakersを利用する
はじめに
Sidekiqは優れたバックグラウンド処理のためのgemです。しかしながら、後ろで動いているのがredisである以上、あまり多くの機能を求めることはできません。一部の機能はRubyのコードによって実装されており、Rubyの言語仕様に引きずられます。
そこで昨今、注目を浴びているのがSneakersです。こちらは後ろでRabbitMQと呼ばれるerlangで書かれたメッセージブローカーが利用されます。巷でメッセージブローカーと言えば、kafkaが有名ですが、RabbitMQもまた非常に優れたブローカーです。
という記事を読んだので、Sneakersを試してみました。
RabbitMQは過去に少しだけ触ったことがあったので、そのタフネス具合には何となく及びがつきます。殺されても殺されても必死に立ち上がってくるerlangのプロセスは、まるでピクミンのような愛らしさすら感じます。
正直、よほど忙しいシステムでない限り、kafkaを利用せずとも、RabbitMQで十分なのではないかな、などと考えていたりします。
実装
RabbitMQのインストールは環境によって異なるので、各々の環境に合わせて適宜インストールして下さい。こちらのインストールで躓くことは、まずないと思われます。centosであれば、yumコマンドで一発です。
$ sudo yum --enablerepo=epel -y install rabbitmq-server
RabbitMQを起動しましたら、次はgemをインストールします。
$ gem install sneakers
config/application.rbを編集することで、ActiveJobのアダプターの指定をsneakersに変更します。また、ActiveJob経由でworkerを呼び出すので、app/jobsに新しいjobを追加します。併せてapp/workersに追加したjobを呼び出す為のworkerも追加しましょう。
最後にworkerを起動するためのRakeタスクを定義します。
定義するとは言っても、Rakefileで必要なファイルをrequireするだけです。とても親切ですね。config/applicationをrequireしている次の行あたりに記述しておけば問題ないでしょう。
require 'sneakers/tasks'
これで準備は完了です。workerを起動します。
$ WORKERS=MyJobWorker bundle exec rake sneakers:run
あとはrails cからMyJob.perform_later()などとして、jobをenqueueします。するとRabbitMQに接続が行われて、キューイングが行われている様子がログから確認できます。
2018-07-09T17:32:58Z p-23978 t-gneflh16c INFO: publishing <{"job_class":"MyJob","job_id":"5ae4391a-53a6-44d4-84ed-982a4474ec2c","provider_job_id":null,"queue_name":"my_job","priority":null,"arguments":[],"executions":0,"locale":"en"}> to [my_job]
Enqueued MyJob (Job ID: 5ae4391a-53a6-44d4-84ed-982a4474ec2c) to Sneakers(my_job)
=> #<MyJob:0x005570d9b1cd40 @arguments=[], @job_id="5ae4391a-53a6-44d4-84ed-982a4474ec2c", @queue_name="my_job", @priority=nil, @executions=0>
2018-07-09T17:32:58Z p-23846 t-gpvltnqp4 DEBUG: [worker-my_job:1:q8yo49][#<Thread:0x0055cb391d8fd0>][my_job][#<Sneakers::Configuration:0x0055cb39bec170>] Working off: "{\"job_class\":\"MyJob\",\"job_id\":\"5ae4391a-53a6-4
4d4-84ed-982a4474ec2c\",\"provider_job_id\":null,\"queue_name\":\"my_job\",\"priority\":null,\"arguments\":[],\"executions\":0,\"locale\":\"en\"}"
Perform!
RabbitQMには非常に優れた管理UIや、とても便利なAPIが付いてきます。RubyのSDKも充実しておりますので、これらをrails側から叩くことが容易であると考えると、なかなか悪くない選択肢なのではないかと思います。