Railsコントローラーの内部からサーバーにヒットしたいだけですが、応答を待ちません。これは可能ですか?(他のスレッドを起動しないと、パフォーマンス上の理由から実行できません)
6 に答える
コントローラーから request-url ジョブをキューに追加します。
次に、キューから読み取り、要求を実行するバックグラウンド プロセスを実行します。
これにより、コントローラー アクションから要求パフォーマンスの遅延が取り除かれます。
Rails 4.2 には、特定のバックエンド実装から抽象化された、これを行う方法が含まれています。これは ActiveJob と呼ばれます。
https://github.com/rails/rails/tree/master/activejob
これを Sidekiq サービスで使用する例を次に示します。
https://github.com/mperham/sidekiq/wiki/Active-Job
古いバージョンの Rails を使用している場合は、キュー サービスの 1 つを直接使用することもできます。
可能ですが、 ruby eventmachineを使用する必要があります
次に、em-http-requestを使用して非同期 http リクエストを実行できます。つまり、次のようになります。
最初にgemをインストールします
gem install 'eventmachine'
gem install 'em-http-request'
次に、コードを試してください
require 'rubygems'
require 'eventmachine'
require 'em-http'
urls = %w(http://www.google.com http://www.rorra.com.ar)
pending = urls.size
EM.run do
urls.each do |url|
http = EM::HttpRequest.new(url).get
http.callback {
puts "#{url}\n#{http.response_header.status} - #{http.response.length} bytes\n"
puts http.response
pending -= 1
EM.stop if pending < 1
}
http.errback {
puts "#{url}\n" + http.error
pending -= 1
EM.stop if pending < 1
}
end
end
ruby にはいくつかの異なる HTTP ライブラリがあります。それらのいくつかは、Ruby の「非同期」リクエストを許可します。通常は別のスレッドになりますが。パフォーマンス上の理由からそれができないと言うのは間違っているかもしれません。
HTTPClientは、必ずしも最も人気があるわけではありませんが、私の好みの HTTP クライアント ライブラリです。HTTPClient を使用すると、次のことができます。
conn = HTTPClient.new.get_async(" http://example.com ")
通常は、返された接続オブジェクトを使用してリクエストがいつ完了したかを確認しますが、返された接続オブジェクトを無視することもできます。どちらの場合も、実際の HTTP リクエストは別のスレッドで行われるため、メイン スレッドはそれを待機せず、他のコードの実行を続行できます。
他の ruby http クライアント ライブラリも非同期モードを提供します。http 要求を行うスレッドを起動するだけで、自分でそれを行うこともできます。気にしない場合は、スレッドの完了を待つ必要さえありません。スレッドプールを使用するために、 concurrent-rubyのいくつかのツールを使用できます。また、他の誰かが既に書いたコードを使用して、パフォーマンスに関する懸念を最小限に抑えることもできます。おそらく、concurrent-ruby の Future です。
本当にスレッドを使用したくない場合は、他の誰かが提案したように、基本的に EventMachine を使用する必要があります。ただし、これが必ずしもパフォーマンスの向上につながるとは思いません。
スレッドを作成していることがわからない場合に非同期リクエストを作成できるコンパイル済みの C gem がいくつかありますが、C コードは C ランドでスレッドを作成している可能性があります。スレッドは基本的に、やりたいことを非同期に行う方法です。または、EventMachine のような複雑なイベント/ファイバー ベースのソリューションももちろんあります。
Rails 4.2 では、ActiveJob を使用して HTTP リクエストをバックグラウンド プロセスとしてキューに入れることができます。これは、HTTP 要求を開始する別の方法ですが、コントローラーを待機させません。ただし、ActiveJob のバックエンドをセットアップする必要があり (いくつかの選択肢があります)、バックエンドはまったく別のプロセス (おそらく複数のプロセス) で実行されます... または、バックエンドはあなたのためにスレッドを作成します。
スレッドへの抵抗を放棄することを検討することをお勧めします。スレッドはこれを処理するための本当に優れた方法であり、パフォーマンスの問題になるべきではありません-私はおそらく並行ルビーを使用し、それがあなたに与えるより高いレベルの抽象化のいくつかを使用しますフューチャー (内部ではまだスレッドの観点から実装されています)。スレッド コードを自分で直接記述する必要がないようにし、自分が何をしているかを知っている他の人によって記述されたライブラリを使用し、パフォーマンス上の懸念に対して合理的にすべてをセットアップします。 . または、本当にスレッドを回避したい場合は、スレッドを使用しないバックエンド アダプターで ActiveJob を使用します。個人的には、EventMachine ルートは使用しません。これは、非同期の http 要求のためだけに、多くの処理が追加されるためです。
または、そうです、単に HEAD リクエストを作成し、それが十分に高速であることを確認してください。
または、確かに、応答を待たずにすぐにソケットを閉じることができるように、ソケットを直接開くことに関する Myst の回答は興味深いようです。