limit_req の制限のかかりかたがなかなか掴めなかったのでメモ。
まずは
limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=1r/s;
limit_req limit_zone;
とすると、leaky bucketというアルゴリズムに基いてIPアドレスごとに1r/sの制限がかかる。超えたぶんは503。
limit_req limit_zone burst = 5;
burst オプションをつけると burst ぶんのリクエスト数まで受け付けるようになって(かつrateに従ってレスポンスを返す)、超えたぶんは503。
limit_req limit_zone burst = 5 nodelay;
になると、burstぶんのリクエストまでは即時レスポンスを返す。それ以降はrateに従う。超えたぶんは503。
何が掴めなかったかというと、burstをつけた場合、burstを超えたと判断されるタイミングは?とか、超えたと判断されたら次はいつburstできるの?とか、そのあたり。nodelayをつけたり外したりしてパニックになってたw
基本的にどのオプションでもleaky bucketのアルゴリズムで処理されていくというのは同じで、nodelayをつけるとレスポンスを即時返すというだけなんだけど、よくわからないうちはnodelayなしで検証するとわかりやすいと思う。
leaky bucketのバケツはqueue構造になっていて、burstはqueueの深さ。rateがworkerの仕事量。nodelayは見かけ上queueと関係なく即時処理されているように見せかけるだけ(つまりqueueには残っている)という感じになっているようなので、burstを超えたかどうか判定されるのはqueueが溢れた時。次にburstできるのはqueueが空になった時だった。
rateを小さく、burstを想定するリクエストより少し大きめにしておいてnodelayを有効にするとDoS対策としても使えそうかな?