2

我正在尝试了解如何将事件 Web 服务器与异步 sinatra 和 EventMachine 结合使用。

在下面的代码中,“/”上的每个请求都会向 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

这会产生非常高的每秒请求数。凉爽的!

4

1 回答 1

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 适配器。

于 2012-08-12T01:51:10.737 回答