2014年9月15日月曜日

Railsのテストサーバ(WEBric)はシングルスレッド?!

このところ、Rails漬けな生活を余儀なくされつつあって、四苦八苦しながら日々少しづつ山を崩していますが、地味にハマったのでメモ。

Railsな人には常識なのかもしれませんが、Railsの開発サーバである、WEBrickは、実はシングルスレッドで動作しているので、同時に複数のリクエストを処理できません。

なお、当然これはWEBrickの制約なので、Rails自体がマルチスレッドで動作しないわけではありません。

簡単に実験してみました。(Ruby 2.1.2 + Rails4)

rails g controller test1 index
rails g controller test2 index
っと、2つページを作成し、test1のindexアクションにこんな感じでスリープを入れます。


class Test1Controller < ApplicationController
  def index
    sleep(30)
  end
end

rails s
でWEBrickを起動し、localhost:3000/test2/indexにアクセスします。
普通にtest2のページが表示されるはずです。
では、その状態で別のブラウザまたは別のタブを開いて、localhost:3000/test1/indexにアクセスします。

開くのに30秒ほどかかるはずです。

では、test1にアクセスして、読み込み中のときに、test2を開いてみましょう。
おそらくtest2も応答待ちになったと思います。

ちなみに、Productionモードで起動しても同じでした。

開発用簡易サーバということで、あまり負荷がかかるのを想定されていないのでしょうが、
コントローラに重いトランザクション処理をさせて、別ブラウザで他のページを参照するテストが全く動かなくて焦りました・・・
(RubyというかRails的には、そもそも長時間サーバを専有するようなコードは書くべきではないし、やるなら別スレッドで非同期処理しろってことなんでしょうけど。)

なお、Apache+Passengerの環境では、普通にマルチスレッドで処理されるので、上記のような問題はありませんでした。

開発サーバでもマルチスレッドで動作させたい場合は、unicornなどを使用すると良さそうですが、
開発マシンのメモリがガシガシ食われるのでvagrant環境だとちょっと厳しい。


1 件のコメント:

  1. Ruby 2.3.0に添付のwebrickで確認してみたところ、webrickはマルチスレッドでした。最近のバージョンでは変わったのでしょうかね。
    記事内の方法でも確認できますし、Thread.current.object_idを見ても確認できます。
    unicornは昔も今もシングルスレッドです。

    返信削除