5

解決

開発モードでユニコーンに切り替えています。デッドロック状態を防ぐために、再帰のレベルごとに1つのワーカープロセスが必要なので、2つのワーカープロセスで実行しています。

問題

開発環境でThinサーバーに取り組んでいます。ポート3000(開発環境のデフォルト)を使用しています。私の問題は、サーバーがそれ自体に要求を行うようにすることです。

次のコントローラーがあるとしましょう。

# app/controllers/recursions_controller.rb
class RecursionsController < ApplicationController

    # /recursions
    def index

        # synchronously call recursions#show
        RestClient.get("http://localhost:3000/recursions/1") 

        # finish!
        render :text => 'index'

    end

    # /recursions/:id
    def show

        # finish immediately
        render :text => 'show'

    end

end

対応するルートは次のとおりです。

# config/routes.rb
resources :recursions

これは、最初にリクエストしたときのリクエストログからの出力ですrecursions#index

[INFO] 2013-01-15 12:09:05 -0800 Started GET "/recursions" for 127.0.0.1 at 2013-01-15 12:09:05 -0800
Processing by RecursionsController#index as HTML
Completed 500 Internal Server Error in 60049ms

[FATAL] 2013-01-15 12:10:05 -0800 RestClient::RequestTimeout (Request Timeout):
  app/controllers/recursions_controller.rb:8:in `index'
  Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.8ms)
  Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.7ms)
  Rendered /usr/local/lib/ruby/gems/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (7.4ms)

[INFO] 2013-01-15 12:10:05 -0800 

[INFO] 2013-01-15 12:10:05 -0800 

[INFO] 2013-01-15 12:10:05 -0800 Started GET "/recursions/1" for 127.0.0.1 at 2013-01-15 12:10:05 -0800
Processing by RecursionsController#show as XML
  Parameters: {"id"=>"1"}
  Rendered text template (0.0ms)
Completed 200 OK in 7ms (Views: 5.5ms)

ここで起こっているのは、ある種のデッドロック状態だと思います。リクエストAはリクエストBが戻るまで戻ることができません(再帰的な順序付け、それを助けることはできません)が、リクエストBはリクエストAが戻るまで処理できません(私のWebサーバーに組み込まれている明らかな制限?)。RestClientがタイムアウトするとデッドロックが解決され、例外が発生してリクエストAが500で終了します。その場合にのみ、リクエストBが処理されますが、現時点では無効です。

私のウェブサーバーは同時リクエストを処理できないようです。そうは言っても、ここに私の質問があります:

  1. この方法で制限されていない開発環境で切り替えることができるWebサーバーはありますか?本番環境ではUnicornを使用しており、複数のワーカープロセスを生成できるため、同時リクエストを処理できますが、Unicornは開発環境には重すぎるようです。Unicornを私の問題の解決策にするのと同じことが、ログ出力の読み取りを困難にする可能性があります。これが私の最後の手段です。

  2. 明らかな同時リクエストの制限を回避する、Rails / Rackフレームワークへのリクエストを行うためのトリッキーな方法はありますか?

  3. 誰かが私にこのlimationを明示的に述べているドキュメントを提供できますか?それがすべてのシングルプロセスRubyonRails Webサーバーに固有の制限なのか、それとも単にThinだけなのかはわかりません。

注:これは、私が抱えているブロッキングの問題を示すための単なるトイプロブレムです。これの実際の理由を知る必要がある場合は、一部のHTTPサービスをインフラストラクチャの別の部分からRoRアプリに移動しているということです。RoRアプリは、コード内のさまざまなポイントでこれらのサービスを使用するため、これらのサービスのクライアントコードはそのままにして、実装のみを変更しようとしています。これは、循環HTTPリクエストを作成することを意味します。これは、後日、すべてが安定したときに最適化されます。

4

2 に答える 2

5

デフォルトでは、アプリは一度に1つのリクエストのみを処理するというのは正しいことです。この制限はRack::Lockミドルウェアによって実装されます。使用するWebサーバーに関係なく適用されます。

config.thread_safe!これは、適切なenvironment.rbファイルを呼び出すことで変更できます。ただし、Railsの開発モードコードの再読み込みはスレッドセーフではなく、この設定では無効になっているため、開発では実際には使用できません。まさに何のconfig.thread_safe!は、レール構成ガイドで説明されています。

乗客、捕虜、ユニコーンはすべて、複数のインスタンスを簡単に実行できるようにします。

于 2013-01-15T20:57:45.660 に答える
1

私は私のクライアントの1人とこの正確な問題に遭遇しました。説明どおりです。プロセスが1つしかないシングルスレッドのウェブサーバーを実行しているため、一度に1つのクライアントに制限されます。2番目の要求、またはループバック要求を行うと、2番目の要求は最初の要求がタイムアウトするまでOSによってキューに入れられます。

ユニコーンに切り替えても本質的に問題は解決しませんが、私たちの場合はユニコーンを使用していて、ワーカー数を「2」に増やしただけです。私は労働者数を増やす方法を推奨するほど薄いことに精通していませんが、間違いなく方法があります。それ以外の場合は、ユニコーンを使用します。切り替えを行うと、開発/製品のパリティも向上するため、価値があるかもしれません。

于 2013-01-15T20:38:56.830 に答える