如果你在Sinatra中的回复返回一个'eachable'对象,那么Sinatra的事件循环将“每个”你的结果并以流式方式产生结果作为HTTP响应。但是,如果有对Sinatra的并发请求,它将在处理另一个请求之前迭代一个响应的所有元素。如果我们对某些数据库查询的结果有一个游标,那意味着我们必须等待所有数据在处理并发查询之前可用。
我看过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秒内返回2个请求)。运行ab -c 10 -n 50 http://locahost:3000/delay/5
(Apache基准实用程序)也会在总时间(~25秒)内返回合理的值。 Firefox表现出与Chrome相同的行为。什么是与命令行实用程序不同的浏览器?
答案 0 :(得分:4)
所以最后,我发现该示例确实有效,我最终可以让Sinatra同时流式传输每个结果,主要是使用Pusher和Async页面中的EM.defer
想法。卷曲和Apache基准测试证实这是有效的。
它在浏览器中不起作用的原因是浏览器限制了到同一URL的连接数。我知道并发连接到单个域(也是一个低数字)的限制,但不是(似乎)所有与单个URI的连接都被序列化:
http://maillist.caucho.com/pipermail/resin-interest/2009-August/003998.html
我不知道这是否可配置,我只在Firefox中看到域范围的配置,但这就是问题。
答案 1 :(得分:-1)
当您要处理对象的响应时,请执行以下操作:
fork do
handle request...
exit 99
end
如果您不需要等待此子进程结束..使用:
child = fork do
handle request...
exit 99
end
Process.detach(child)
这是一种处理多个请求的简单方法,但是我不确定您可能正在使用哪些ORM来进行这些数据库查询,但是如果有多个进程尝试访问数据库,您可能会遇到表/行级别锁定问题是你说处理请求时的意思......