问题描述
Sinatra 应用程序接收对长时间运行任务的请求并 EM.defer,在 EM 的 20 个线程的内部池中启动它们.当运行的EM.defer超过20个时,通过EM.defer存储在EM的线程队列中.
Sinatra app receives requests for long running tasks and EM.defer them, launching them in EM's internal pool of 20 threads. When there are more than 20 EM.defer running, they are stored in EM's threadqueue by EM.defer.
然而,似乎 Sinatra 不会为任何请求提供服务,直到有可用的 EM 线程来处理它们.我的问题是,Sinatra 不是假设使用主线程的反应器来服务所有请求吗?为什么我在提出新请求时会在线程队列中看到添加?
However, it seems Sinatra won't service any requests until there is an EM thread available to handle them. My question is, isn't Sinatra suppose to use the reactor of the main thread to service all requests? Why am I seeing an add on the threadqueue when I make a new request?
重现步骤:
Access /track/
Launch 30 /sleep/ reqs to fill the threadqueue
Access /ping/ and notice the add in the threadqueue as well as the delay
重现它的代码:
require 'sinatra'
#monkeypatch EM so we can access threadpools
module EventMachine
def self.queuedDefers
@threadqueue==nil ? 0: @threadqueue.size
end
def self.availThreads
@threadqueue==nil ? 0: @threadqueue.num_waiting
end
def self.busyThreads
@threadqueue==nil ? 0: @threadpool_size - @threadqueue.num_waiting
end
end
get '/track/?' do
EM.add_periodic_timer(1) do
p "Busy: " + EventMachine.busyThreads.to_s + "/" +EventMachine.threadpool_size.to_s + ", Available: " + EventMachine.availThreads.to_s + "/" +EventMachine.threadpool_size.to_s + ", Queued: " + EventMachine.queuedDefers.to_s
end
end
get '/sleep/?' do
EM.defer(Proc.new {sleep 20}, Proc.new {body "DONE"})
end
get '/ping/?' do
body "pong"
end
我在 Rack/Thin(没有 Sinatra)上尝试了同样的事情并且按预期工作,所以我猜是 Sinatra 造成的.
I tried the same thing on Rack/Thin (no Sinatra) and works as it's supposed to, so I guess Sinatra is causing it.
Ruby version: 1.9.3.p125
EventMachine: 1.0.0.beta.4.1
Sinatra: 1.3.2
OS: Windows
推荐答案
好的,看来 Sinatra 默认以线程模式启动 Thin,导致上述行为.您可以添加
Ok, so it seems Sinatra starts Thin in threaded mode by default causing the above behavior.You can add
set :threaded, false
在您的 Sinatra 配置部分,这将防止 Reactor 在单独的线程上推迟请求,并在负载下阻塞.
in your Sinatra configure section and this will prevent the Reactor defering requests on a separate thread, and blocking when under load.
这篇关于为什么 Sinatra 请求需要 EM 线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!