Ruby 使用Thin和Sinatra异步迭代请求响应

Ruby 使用Thin和Sinatra异步迭代请求响应,ruby,concurrency,sinatra,thin,eventmachine,Ruby,Concurrency,Sinatra,Thin,Eventmachine,如果您在Sinatra中的响应返回一个“eachable”对象,Sinatra的事件循环将“each”您的结果,并以流式方式作为HTTP响应生成结果。但是,如果存在对Sinatra的并发请求,它将在处理另一个请求之前遍历一个响应的所有元素。如果我们有一个指向某个DB查询结果的游标,这意味着在处理并发查询之前,我们必须等待所有数据可用 我看过async sinatra gem,认为这可以解决我的问题,但我尝试了以下示例: require 'sinatra/async' class AsyncTe

如果您在Sinatra中的响应返回一个“eachable”对象,Sinatra的事件循环将“each”您的结果,并以流式方式作为HTTP响应生成结果。但是,如果存在对Sinatra的并发请求,它将在处理另一个请求之前遍历一个响应的所有元素。如果我们有一个指向某个DB查询结果的游标,这意味着在处理并发查询之前,我们必须等待所有数据可用

我看过async sinatra gem,认为这可以解决我的问题,但我尝试了以下示例:

require 'sinatra/async'

class AsyncTest < Sinatra::Base
  register Sinatra::Async

  aget '/' do
    body "hello async"
  end

  aget '/delay/:n' do |n|
    EM.add_timer(n.to_i) { body { "delayed for #{n} seconds" } }
  end
end
需要'sinatra/async'
类AsyncTest
/delay/5
请求并没有像我预期的那样同时工作,即我同时发出3个请求,Chrome的调试器记录了大约5、10和15秒的响应时间

我是否缺少一些设置,或者是否有其他方法告诉Sinatra/Thin以并发方式处理请求

更新:这里有另一个扳手(或者可能会清理):
同时运行
curl-i
具有正确的行为(每个请求在~5秒内返回2个请求)。运行
ab-c10-n50
(Apache基准测试实用程序)也会在总时间(约25秒)内返回一些合理的结果。Firefox表现出与Chrome相同的行为。浏览器与命令行实用程序有什么不同?

当您准备处理对象的响应时,请执行以下操作:

fork do
  handle request...
  exit 99
end
如果您不需要等待此子进程结束。。带有:

child = fork do
  handle request...
  exit 99
end

Process.detach(child)

这是一种处理多个请求的简单方法,但是我不确定您在这些DB查询中使用的ORM是什么,但是如果您说的是处理请求,那么在多个进程试图访问DB时,您可能会遇到表/行级锁定问题…

因此,最后,我发现这个例子确实有效,我最终可以让Sinatra同时流式处理每个可处理的结果,主要是使用Pusher和Async页面中的
EM.defer
思想。curl和Apache基准测试证实了这一点

它在浏览器中不起作用的原因是浏览器限制了到同一URL的连接数。我知道对单个域的并发连接有一个限制(也是一个较低的数字),但并不是(似乎)对单个URI的所有连接都是序列化的:


我不知道这是否是可配置的,我只在Firefox中看到域范围的配置,但这就是问题所在。

问题不是异步处理DB请求,而是异步将Sinatra响应返回给客户端。我知道EventMachine将允许您
延迟
a
proc
,并在延迟代码完成时执行回调
proc
。顺便说一下,讨论中的数据库是MongoDB,我们有一个指向返回结果的游标。问题是告诉Sinatra并发地迭代游标,并并发地从独立游标生成响应。