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

4
如果Sinatra的响应返回一个'eachable'对象,Sinatra的事件循环将'each'您的结果,并以流式方式在HTTP响应中产生结果。但是,如果有并发请求到达Sinatra,则它将在处理另一个请求之前遍历一个响应的所有元素。如果我们有一些DB查询结果的光标,这意味着我们必须等待所有数据可用后才能处理并发查询。
我已经查看了async-sinatra gem和http://macournoyer.com/blog/2009/06/04/pusher-and-async-with-thin/,认为它们可以解决我的问题,但我尝试了这个示例:
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

同时,我希望/delay/5请求可以像我期望的那样并发工作,即我同时发出3个请求,Chrome调试器将响应时间记录为大约5、10和15秒。

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

更新:这里还有另一个问题(或者可能解决了问题):curl -i http://localhost:3000/delay/5在并发运行时具有正确的行为(每个请求都在约5秒内返回)。运行ab -c 10 -n 50 http://locahost:3000/delay/5(Apache基准实用程序)也对总时间返回了合理的结果(约25秒)。Firefox表现与Chrome相同。浏览器与命令行实用程序有何不同?

2个回答

4
最终,我发现这个例子确实起作用,我最终可以使用Pusher和Async页面中的EM.defer思想来同时流式处理结果,并通过curl和Apache基准测试确认了这一点。但是,它在浏览器中不起作用的原因是因为浏览器限制了对同一URL的连接数量。我知道单个域名的并发连接数也有限制(也很低),但我不知道所有对单个URI的连接都被串行化:

http://maillist.caucho.com/pipermail/resin-interest/2009-August/003998.html

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


-1

当你要处理对象的响应时,请执行以下操作:

fork do
  handle request...
  exit 99
end

如果您不需要等待此子进程结束,请使用:

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

Process.detach(child)

这是一种处理多个请求的简单方法,但我不确定您在使用哪种ORM进行数据库查询,如果多个进程尝试访问数据库时可能会出现表/行级锁定问题,如果这就是您所说的处理请求的方式...


问题不在于异步处理数据库请求,而在于异步返回Sinatra的响应给客户端。我知道EventMachine可以让你defer一个proc,并有一个回调proc在延迟的代码完成时执行。顺便说一下,所涉及的数据库是MongoDB,并且我们拥有一个返回结果的游标。问题在于告诉Sinatra并发地迭代游标,并同时从独立的游标生成响应。 - Kenny Peng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接