4

如果您在 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 以并发方式处理请求?

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

4

2 回答 2

4

所以最后,我发现这个例子确实有效,我最终可以让 Sinatra 并发流式传输每个结果,主要是使用EM.deferPusher 和 Async 页面中的想法。curl 和 Apache 基准测试证实这是有效的。

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

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

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

于 2010-11-10T16:08:36.657 回答
-1

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

fork do
  handle request...
  exit 99
end

如果你不需要等待这个子进程结束..用:

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

Process.detach(child)

这是一种处理多个请求的简单方法,但是我不确定您可能会为这些数据库查询使用什么 ORM,但是如果您是这样的话,您可能会遇到多个进程尝试访问数据库的表/行级锁定问题意思是当你说处理请求时......

于 2010-10-16T05:41:26.517 回答