我正在尝试了解如何使用异步sinatra和EventMachine的组合来使用公平的Web服务器。
在下面的代码中,'/'上的每个请求都会为google生成一个新的异步http请求。是否有一个优雅的解决方案来检测请求是否已在进行并等待其执行?
如果我在'/'上有100个并发请求,则会向Google后端生成100个请求。最好有一种方法来检测已经存在正在进行的后端请求并等待其执行。
感谢您的回答。
require 'sinatra'
require 'json'
require 'eventmachine'
require 'em-http-request'
require 'sinatra/async'
Sinatra.register Sinatra::Async
def get_data
puts "Start request"
http = EventMachine::HttpRequest.new("http://www.google.com").get
http.callback {
puts "Request completed"
yield http.response
}
end
aget '/' do
get_data {|data| body data}
end
更新
我实际上发现你可以在同一个http请求中添加几个回调。因此,它很容易实现:
class Request
def get_data
if !@http || @http.response_header.status != 0
#puts "Creating new request"
@http = EventMachine::HttpRequest.new("http://www.bbc.com").get
end
#puts "Adding callback"
@http.callback do
#puts "Request completed"
yield @http.response
end
end
end
$req = Request.new
aget '/' do
$req.get_data {|data| body data}
end
这每秒提供非常多的请求。酷!
答案 0 :(得分:1)
你根本不需要使用sinatra / async来实现它,只需使用一个事务服务器(Thin,Rainbows!,Goliath)运行它。
查看em-synchrony以获取多个并行请求的示例,而不引入意大利面条回调代码:
require "em-synchrony"
require "em-synchrony/em-http"
EventMachine.synchrony do
multi = EventMachine::Synchrony::Multi.new
multi.add :a, EventMachine::HttpRequest.new("http://www.postrank.com").aget
multi.add :b, EventMachine::HttpRequest.new("http://www.postrank.com").apost
res = multi.perform
p "Look ma, no callbacks, and parallel HTTP requests!"
p res
EventMachine.stop
end
是的,你可以在你的Sinatra行动中运行它。
另请查看Faraday,特别是使用EM适配器。