Sinatra アプリは、長時間実行されるタスクの要求を受け取り、それらを EM.defer して、EM の 20 スレッドの内部プールで起動します。20 を超える EM.defer が実行されている場合、それらは EM.defer によって EM のスレッドキューに格納されます。
ただし、それらを処理する EM スレッドが利用可能になるまで、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