60min.第13回「Background Job Worker座談会」
ursmから、このようなものが何故必要なのか、そしてidobataで実際にどう利用しているのか、ということを話してもらった。
なぜ必要なのか
Railsのプロセスはだいたい200Mくらいはメモリを使うので、たとえばそれを32個上げるとするとそれだけで 200M * 32 でだいたい6Gくらいのメモリを使うことになる。(そして、メモリは普通有限なのだ)
たとえば1秒かかる処理があると、同時に捌けるリクエストは32個になってしまい、33個目は1秒後に処理が開始されることになって、レスポンスを返すまで2秒かかる。
これが1秒ならまだいいが、普通、処理待ちをしている間にもどんどんリクエストは来るので、雪だるま式に処理待ちのリクエストが増えていくことだろう。
なので、同期処理が必要ない部分は、積極的に非同期処理に逃がしていかないといけない。
Background Job Workerはどれを使えばいいの?
2013年では以下の4つのライブラリを抑えておけば十分で、それぞれ特徴があるからアプリの特性やインフラと相談して決めるのがいいよということ。
まず、ResqueとSidekiqについて。 仕組みはだいたい同じだが、Resqueは処理がプロセス、Sidekiqはスレッドになっている。
Ruby(MRI)はグリーンスレッドなのとMRIは1.9以降はネイティブスレッドだけどGVLがあるのと、マルチスレッドがらみのメモリリークやバグに悩まされたくないなら、とりあえずResqueという選択でもいいかもしれない。
queue_classicは、ジョブキューがPostgreSQLのPubSubを使っているので、ポーリングしている他のライブラリに比べて仕組みがクール。Redis等を入れなくてもいいので便利。
girl_fridayは、ジョブキューを自身のプロセスの中に持っている。ジョブを依頼する側と処理する側が同じプロセスになるので、ちょっと面白い(強引な)こともできたりする。ただ、Railsのプロセスが落ちるとジョブキューも無くなってしまうので、Redisバックエンドの仕組みを入れておいたほうがいいだろう。
因みに、私はとあるアプリでインフラにあまり手をいれたくなかったので、girl_fridayのオンメモリで実装したことがあります。ただ、それは運用の支援ツールみたいなやつで、「だめなら再実行すればいいからさくっと作ってほしいという話だったからなので、なるべくRedisバックエンドにしましょう。
まとめ
あまりこの辺に詳しくないなら、まずはResqueを使おう。ただ、Sidekiqでも実感できる程の処理の遅さはないと思う。
DBMSがPostgreSQLならqueue_classicは試してみる価値があるよ。
girl_fridayは、仕組みが面白いから教養として使ってみるといいかも。
ちなみに、idobataではSidekiqとgirl_fridayを使っているとのこと。(なんで2つあるのかは、忘れてしまったそうな)