時々HTTPサーバで特定のリクエストに対してだけわざと時間をかけてレスポンスを返したいことがある。例えばエッジケースだが、プロキシサーバの負荷テストをする際、バックエンドのサーバが詰まっている状況を再現するためにわざとsleep
を入れたいことがある。しかし、単純なsleepだとリクエストどころかサーバ自体をブロックしてしまうので一工夫が必要である。で、echo-nginx-moduleやngx_luaにはnon-bloking behaviorなsleepが用意されているので特定のリクエストはブロックしつつ、ほかのリクエストは並行して処理するといったことが簡単にできる。
echo-nginx-moduleのecho_sleepを使ったnon-blocking sleep
echo-nginx-moduleは単にecho
するためのモジュールである・・・そう、思っていた時期が私にもありました。README.mdを見ればわかるとおり、このモジュールは何故echoモジュールなんて名前が付いてるのかわからないくらい多機能である。
例えばさっき言ったnon-blocking behaviorなsleep処理はechoモジュールだとこう書ける。
location /echo_take_1sec {
echo_sleep 1;
echo "OK";
}
このロケーションにリクエストすると1秒後にOK
が返ってくる。そして次に述べることが重要なのだが、echo_sleep
はリクエストをブロックするが、nginxのプロセスはブロックしない。つまりnginxは特定のリクエストを指定秒数だけブロックしつつ、ほかのリクエストを並行して処理することができる。
ngx_luaのngx.sleep()を使ったnon-blocking sleep
ngx_luaではecho_sleep
相当のAPIとしてngx.sleep()
が提供されている。さっきと同じことをngx_luaでやるコードは以下の通り。
location /echo_take_1sec {
content_by_lua_block {
ngx.sleep(1)
ngx.say("OK")
}
}