LoginSignup
2
2

More than 5 years have passed since last update.

em-http-requestで複数のダミーサーバーに同時リクエストするサンプル

Posted at

非同期HTTPクライアントem-http-requestを用いて複数のサーバーに同時リクエストできることを確認します。

クライアント

em-http-client.rb
require 'eventmachine'
require 'em-http'

# ホスト:ポート生成
def host(i)
  "http://localhost:#{9292 + i}/"
end

EM.run do
  # 3つのリクエストを作成。
  # localhostのポート9292, 9293, 9294で複数のサーバーが動いていることを想定。
  # durationというパラメータ(後述)に適当な整数を渡している。
  requests = Array.new(3) do |i|
    EM::HttpRequest.new(host(i)).get :query => {'duration' => (3 + i)}
  end
  # 非同期リクエストのコールバック登録
  requests.each do |request|
    request.callback do
      puts request.response
    end
    request.errback do
      puts "Error: #{request.error}"
    end
  end
end

ダミーサーバー

寝るだけのRackアプリケーション

整数パラメータdurationに指定された秒数だけ寝た後で適当なJSONを返す簡単なRackアプリケーションを作ります。

sleeper.ru
require 'rack/response'
require 'json'

class Sleeper
  def call(env)
    req = Rack::Request.new(env)
    t = req["duration"].to_i
    puts "Going to sleep for #{t} seconds..."
    sleep t
    Rack::Response.new.finish do |res|
      j = {pid: $$, duration: t}.to_json
      res.write j
    end
  end
end

run Sleeper.new

WEBrickサーバー起動

上記Rackアプリケーションを実行します。コマンドラインから整数引数を受け取り、ポート番号に加え、RackアプリケーションをWEBrickサーバー上で実行します。ポート番号を可変にしているのは後でこのサーバーを別々のポートで複数起動するためです。
(走りっぱなしでkillし忘れるのが嫌なのでEM.deferを使用して30秒後に自分自身にSIGINTを送信しています。Rack::Serverではtrap(:INT)でサーバーをshutdownしています。)

spawn_sleeper.rb
require 'rack'
require 'eventmachine'
EM.run do
  # 30秒後に終了。
  EM.defer do
    sleep 30
    puts "Stopping server ..."
    Process.kill :INT, $$
  end
  puts "Starting server ..."
  # 上記のsleeper.ruを指定してサーバー開始。
  Rack::Server.start server: "webrick", Port: (9292 + ARGV[0].to_i), config: "sleeper.ru"
  puts "Bye."
  EM.stop
end

動作確認

下記動作確認はMac OS Xで行っていますが、Linuxでも同様のはずです。
shellはbashを想定しています。

ダミーサーバー起動

# ポート9292, 9293, 9294でサーバーをバックグラウンド実行。
for i in `seq 0 2`
do
  ruby spawn_sleeper.rb $i &
done

クライアント起動

ruby em-http-client.rb

各サーバーからのレスポンスが3, 4, 5秒後に出力されます。
非同期複数リクエストなので約5秒後にはすべてレスポンスが得られます。逐次同期的に実行していたらおよそ3 + 4 + 5 = 12秒後となっていたでしょう。

Going to sleep for 4 seconds...
Going to sleep for 3 seconds...
Going to sleep for 5 seconds...
localhost.localdomain - - [13/Dec/2014:13:58:18 JST] "GET /?duration=3 HTTP/1.1" 200 26
- -> /?duration=3
{"pid":92341,"duration":3}
localhost.localdomain - - [13/Dec/2014:13:58:18 JST] "GET /?duration=4 HTTP/1.1" 200 26
- -> /?duration=4
{"pid":92342,"duration":4}
localhost.localdomain - - [13/Dec/2014:13:58:18 JST] "GET /?duration=5 HTTP/1.1" 200 26
- -> /?duration=5
{"pid":92343,"duration":5}

その他

em-synchronyも試してみたいです。

以上。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2