1

イベント化されたサブスクリプションを介してキューからメッセージをプルするコンシューマーがあります。これらのメッセージを受け取り、かなり遅い http インターフェイスに接続します。8 つのワーカー プールがあり、それらがすべていっぱいになったら、キューからの要求のプルを停止し、http ジョブで動作しているファイバーを動作させ続ける必要があります。これが私が一緒に投げた例です。

def send_request(callback)
  EM.synchrony do

    while $available <= 0

      sleep 2 

      puts "sleeping"
    end 
    url = 'http://example.com/api/Restaurant/11111/images/?image%5Bremote_url%5D=https%3A%2F%2Firs2.4sqi.net%2Fimg%2Fgeneral%2Foriginal%2F8NMM4yhwsLfxF-wgW0GA8IJRJO8pY4qbmCXuOPEsUTU.jpg&image%5Bsource_type_enum%5D=3'
    result = EM::Synchrony.sync EventMachine::HttpRequest.new(url, :inactivity_timeout => 0).send("apost", :head => {:Accept => 'services.v1'})

    callback.call(result.response) 
  end 
end

def display(value)
  $available += 1
  puts value.inspect
end

$available = 8 

EM.run do
  EM.add_periodic_timer(0.001) do
    $available -= 1
    puts "Available: #{$available}"

    puts "Tick ..." 
    puts send_request(method(:display))
  end 

end

Synchrony ブロックの while ループ内で sleep を呼び出すと、reactor ループが動かなくなることがわかりました。if ステートメント内で sleep を呼び出すと (1 回だけスリープする)、ほとんどの場合、要求が完了するのに十分な時間ですが、せいぜい信頼性が低くなります。EM::Synchrony.sleep を使用すると、メインのリアクター ループが新しい要求を作成し続けます。

メインループを一時停止し、ファイバーの実行を終了させる方法はありますか?

4

1 に答える 1

1
sleep 2

..。

add_periodic_timer(0.001)

真剣ですか?

send_requestループ内で何人が眠っていますか?そしてそれは毎秒1000を追加しています。

これはどうですか:

require 'eventmachine'
require 'em-http'
require 'fiber'

class Worker
  URL = 'http://example.com/api/whatever'

  def initialize callback
    @callback = callback
  end

  def work
    f = Fiber.current
    loop do
      http = EventMachine::HttpRequest.new(URL).get :timeout => 20

      http.callback do
        @callback.call http.response
        f.resume
      end
      http.errback do
        f.resume
      end

      Fiber.yield
    end
  end
end

def display(value)
  puts "Done: #{value.size}"
end

EventMachine.run do
  8.times do
    Fiber.new do
      Worker.new(method(:display)).work
    end.resume
  end
end
于 2012-09-07T07:57:54.223 に答える