nginxでメソッドごとにリクエスト数制限を掛けたい

アプリケーションでどうしても捌けない量のリクエストが一時的に押し寄せてしまう場合、アプリケーションサーバが死ぬのを避けるために GET は制限を掛けたいが、POST はリトライが面倒なのでなるべく通してあげたい、というような要求を nginx で処理できるかどうか。

実装として一番望ましいのは

  • GET は 100 req/sec で制限 (超えたら503)
  • POST は無制限

のようにメソッドごとに別々の制限を掛けることだったのですが、とりあえず HttpLimitReqModule を使うことで、メソッドごとに同一の上限を設定することはできました。

http {
    limit_req_zone $request_method zone=method:1m rate=100r/s;
    server {
        listen 80;
        location / {
            limit_req zone=method;
            proxy_pass http://127.0.0.1:5000/;
        }
    }
}

これで $request_method をキーにして、100req/sec を超えた分を 503 にします。

この設定では GET も POST も同じ上限になりますが、たとえば仮に

  • リクエストの比率が GET : POST = 9 : 1
  • アプリケーションが処理できる上限が 150req/sec
  • そこに 300req/sec が到達する

という場合を考えると GET=270, POST=30 req/sec になるので、

  • GET は 100 req/sec を超えた分 (170 req/sec) が 503
  • POSTは 30 req/sec なのですべてアプリケーションの処理に回る
  • アプリケーションに到達するリクエストは合計 100 + 30 = 130 req/sec

となって、POSTを全部通しつつ限界を超えないような制限ができます。