我试图全面了解在Rack中处理并发请求的选项。我已经使用async_sinatra构建了一个长轮询应用程序,并且现在正在使用throw :async
和/或Thin的--threaded标志来尝试裸机Rack。虽然我对这个问题很熟悉,但仍有一些事情我不能理解。(不,我没有将并发误认为是并行,而且我也理解GIL所施加的限制.)
问题1: 我的测试表明thin --threaded
(即rack.multithread=true
)会在单独的线程中并发运行请求(我假设使用EM),这意味着长时间运行的请求A不会阻塞请求B(IO除外)。这意味着我的应用程序不需要任何特殊编码(例如回调)来实现并发(再次忽略阻塞DB调用、IO等)。这就是我所观察到的,请问它是否正确?
问题2: 还有另一种更常被讨论的实现并发的方法,涉及EventMachine.defer
和throw :async
。严格来说,请求并不是使用线程处理的。它们是按顺序处理的,但是将它们的繁重工作和回调传递给EventMachine,后者使用async.callback在稍后的时间发送响应。当请求A将其工作离线到EM.defer后,请求B开始。这是正确的吗?
问题3: 假设以上两种方式大致正确,它们之间是否存在特定的优劣之处?显然,--threaded
看起来像神奇的子弹。有没有缺点?如果没有,为什么会有人谈论async_sinatra
/throw :async
/async.callback
?也许前者是“我想在重载下使我的Rails应用程序更快”,而后者更适合具有许多长时间运行请求的应用程序? 或者规模是一个因素?这只是猜测。
我正在使用MRI Ruby 1.9.2上的Thin 1.2.11。 (FYI,我必须使用--no-epoll
标志,因为在Ruby 1.9.2中,EventMachine对epoll的使用存在一个长期存在、据称已解决但实际上并未解决的问题。这不是重点,但任何见解都受欢迎。)