nginxでnon-blocking sleep

More than 3 years have passed since last update.

時々HTTPサーバで特定のリクエストに対してだけわざと時間をかけてレスポンスを返したいことがある。例えばエッジケースだが、プロキシサーバの負荷テストをする際、バックエンドのサーバが詰まっている状況を再現するためにわざとsleepを入れたいことがある。しかし、単純なsleepだとリクエストどころかサーバ自体をブロックしてしまうので一工夫が必要である。で、echo-nginx-modulengx_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")
}
}