5.NonBlocking(暫定メモ)
5.1.基本的なNonBlockingな処理
ratpack {
// テストのためにサーバが利用するスレッドは1つに限定
serverConfig {
threads 1
}
handlers {
// ab -n 10 -c 10 http://localhost:5050/test-blocking
// サーバは1スレッドしか扱えないようにしているので、1スレッド(1アクセス)が終わるまで他のアクセスは待ちになる。
// なので、上記のabを実行すると、10ユーザが同時に10アクセスしてきて、各アクセスが5秒待機するので、大体50秒ほどかかる。
// 実行するとコンソールには以下のように出力される
// tart
// end
// start
// end
// start
// end
// start
// end
// start
// end
// start
// end
// start
// end
// start
// end
// start
// end
// start
// end
get ("test-blocking") {
println "start"
sleep(5000) // 5秒待機
println "end"
render "ok"
}
// ab -n 10 -c 10 http://localhost:5050/test-non-blocking
// サーバは1スレッドしか扱えないという同じルールだが、こちらはsleep処理をBlockingな処理としてRatpackに教えている。
// こうすることで、Ratpackは一つしかないアクセスを捌くcomputeスレッドとは別の、Blocking処理専用のBlockingスレッドに別出ししてくれる。
// こうすることで、メインのcomputeすれどは即座の後続の別のアクセスの処理に映ることができる。
// このBlockingに出した別の処理は、終わった時点で自動的に再度このcomputeスレッドに持っどってきてそy利される。
// まるですべて同時平行に動いているように見えるので、上記のabコマンドは5秒で全ての10アクセスが処理される。
// 実行するとコンソールには以下のように出力される
// start
// start
// start
// start
// start
// start
// start
// start
// start
// start
// end
// end
// end
// end
// end
// end
// end
// end
// end
// end
get ("test-non-blocking") {
Blocking.get {
println "start"
sleep(5000) // 5秒待機
println "end"
}.then {
render "ok"
}
}
}
}
5.2.PromiseからさらにNonBlockingな処理を続ける
// 以下のようにすれば、parseで帰ってきたPromiseから更にBlockingでblockingスレッドに処理を別出しすることが出来る。
// ab -n 4 -c 4 -p ./test.json -T "application/json; charset=utf-8" http://localhost:5050/test
// 以下のような感じになる(computeスレッドを1つに限定)
// blockingは複数スレッドになっていることが確認できる。
// start ratpack-compute-13-1
// end ratpack-compute-13-1
// start ratpack-compute-13-1
// end ratpack-compute-13-1
// start ratpack-compute-13-1
// end ratpack-compute-13-1
// main (ratpack-blocking-14-1)
// main (ratpack-blocking-14-4)
// main (ratpack-blocking-14-2)
// start ratpack-compute-13-1
// end ratpack-compute-13-1
// main (ratpack-blocking-14-3)
// ok (ratpack-compute-13-1)
// ok (ratpack-compute-13-1)
// ok (ratpack-compute-13-1)
// ok (ratpack-compute-13-1)
path("test") {
println "start ${Thread.currentThread().name}"
parse(Jackson.jsonNode()).blockingMap {
println "main (${Thread.currentThread().name})"
sleep(5000)
}.then {
println "ok (${Thread.currentThread().name})"
render "ok"
}
println "end ${Thread.currentThread().name}"
}
// 以下のような方法だと、computeスレッド、つまりHTTPを待ち受けて処理するスレッドで、1要求毎に5秒待機してしまうので悪い書き方。
path("test2") {
println "start ${Thread.currentThread().name}"
parse(Jackson.jsonNode()).then {
println "main ${Thread.currentThread().name}"
sleep(5000)
println "ok (${Thread.currentThread().name})"
render "ok"
}
println "end ${Thread.currentThread().name}"
}