worker_processes 1;
events {
worker_connections 200;
}
daemon off;
master_process off;
location /async_sleep {
mruby_rewrite_handler_code '
sleep 3
Nginx.rputs "body"
Nginx.return Nginx::HTTP_OK
';
}
[ubuntu@ubuntu-xenial:~/DEV/ngx_mruby]$ for i in `seq 1 3`; do time curl localhost:58080/async_sleep & done
[1] 25513
[2] 25515
[3] 25516
[ubuntu@ubuntu-xenial:~/DEV/ngx_mruby]$ body
real 0m3.018s
user 0m0.004s
sys 0m0.000s
body
real 0m6.020s
user 0m0.004s
sys 0m0.000s
body
real 0m9.023s
user 0m0.000s
sys 0m0.004s
[1] Done time curl localhost:58080/async_sleep
[2]- Done time curl localhost:58080/async_sleep
[3]+ Done time curl localhost:58080/async_sleep
このように、ひとつのプロセスでsleepを実行すると、シーケンシャルにsleep実行、完了後に次のリクエストのsleepを実行しており、大量にアクセスが集中すると処理が待たされる問題があった。
worker_processes 1;
events {
worker_connections 200;
}
daemon off;
master_process off;
location /async_sleep {
mruby_rewrite_handler_code '
Nginx::Async.sleep 3000
Nginx.rputs "body"
Nginx.return Nginx::HTTP_OK
';
}
このようにプロセスが一つなのにリクエスト単位でsleepがnonblockingに実行される
[ubuntu@ubuntu-xenial:~/DEV/ngx_mruby]$ for i in `seq 1 3`; do time curl localhost:58080/async_sleep & done
[1] 25436
[2] 25437
[3] 25439
[ubuntu@ubuntu-xenial:~/DEV/ngx_mruby]$ body
real 0m3.015s
user 0m0.004s
sys 0m0.000s
body
real 0m3.014s
user 0m0.004s
sys 0m0.000s
body
real 0m3.013s
user 0m0.004s
sys 0m0.000s
[1] Done time curl localhost:58080/async_sleep
[2]- Done time curl localhost:58080/async_sleep
[3]+ Done time curl localhost:58080/async_sleep
全体のmruby実行環境をFiberで書き換えて、async sleepも同じ方式で動くように実装した。これにより、一つのプロセスで複数のsleepがノンブロッキングにできるようになる。