Sinatra 应用程序接收对长时间运行任务的请求并 EM.defer 他们,在 EM 的 20 个线程的内部池中启动它们。当运行的 EM.defer 超过 20 个时,它们由 EM.defer 存储在 EM 的线程队列中。
然而,在有可用的 EM 线程处理它们之前,Sinatra 似乎不会为任何请求提供服务。我的问题是,Sinatra 不是假设使用主线程的反应器来服务所有请求吗?为什么我在发出新请求时会看到线程队列上的添加?
重现步骤:
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 造成的。
Ruby version: 1.9.3.p125
EventMachine: 1.0.0.beta.4.1
Sinatra: 1.3.2
OS: Windows