ard*_*srk 2 ruby queue eventmachine
我有一个用Ruby编写的Http客户端,可以对URL进行同步请求.但是,为了快速执行多个请求,我决定使用Eventmachine.我们的想法是将所有请求排队并使用eventmachine执行它们.
class EventMachineBackend
...
...
def execute(request)
$q ||= EM.Queue.new
$q.push(request)
$q.pop {|request| request.invoke}
EM.run{EM.next_tick {EM.stop}}
end
...
end
Run Code Online (Sandbox Code Playgroud)
原谅我使用全局队列变量.我稍后会重构它.我正在以EventMachineBackend#execute正确的方式使用Eventmachine队列吗?
我在实现中看到的一个问题是它本质上是同步的.我推送一个请求,弹出并执行请求并等待它完成.
任何人都可以建议更好的实施.
The*_*heo 10
您的请求逻辑必须是异步的才能与EventMachine一起使用,我建议您使用em-http-request.您可以在此处找到有关如何使用它的示例,它显示了如何并行运行请求.用于并行运行多个连接的更好的接口是来自同一gem 的MultiRequest类.
如果要对请求进行排队并且只是并行运行固定数量的请求,您可以执行以下操作:
EM.run do
urls = [...] # regular array with URLs
active_requests = 0
# this routine will be used as callback and will
# be run when each request finishes
when_done = proc do
active_requests -= 1
if urls.empty? && active_requests == 0
# if there are no more urls, and there are no active
# requests it means we're done, so shut down the reactor
EM.stop
elsif !urls.empty?
# if there are more urls launch a new request
launch_next.call
end
end
# this routine launches a request
launch_next = proc do
# get the next url to fetch
url = urls.pop
# launch the request, and register the callback
request = EM::HttpRequest.new(url).get
request.callback(&when_done)
request.errback(&when_done)
# increment the number of active requests, this
# is important since it will tell us when all requests
# are done
active_requests += 1
end
# launch three requests in parallel, each will launch
# a new requests when done, so there will always be
# three requests active at any one time, unless there
# are no more urls to fetch
3.times do
launch_next.call
end
end
Run Code Online (Sandbox Code Playgroud)
请注意,在上面的代码中我可能会错过一些细节.
如果您认为在我的示例中很难遵循逻辑,那么欢迎来到优化编程的世界.编写可读的事件代码真的很棘手.一切都倒退了.有时从最后开始阅读会有所帮助.
我假设您不想在开始下载后添加更多请求,它在您的问题中的代码中看起来不像它,但是您是否希望您可以重写我的代码以使用EM::Queue而不是一个常规数组,并删除那个部分EM.stop,因为你不会停止.您可以删除跟踪活动请求数量的代码,因为这不相关.重要的部分看起来像这样:
launch_next = proc do
urls.pop do |url|
request = EM::HttpRequest.new(url).get
request.callback(&launch_next)
request.errback(&launch_next)
end
end
Run Code Online (Sandbox Code Playgroud)
另外,请记住,我的代码实际上并没有对响应做任何事情.响应将作为参数传递给when_done例程(在第一个示例中).我也为成功和错误做同样的事情,你可能不想在真正的应用程序中做.
| 归档时间: |
|
| 查看次数: |
2189 次 |
| 最近记录: |