10
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nginxでレートリミットを設定する

10
Posted at

はじめに

先日、Nginxでレートリミットを設定する機会があったので、内容を備忘録としてまとめておきます。

設定方法

limit_req_zone

まず、どのキーでどれくらいの速さで制限するかというゾーンを定義します。
serverlocation ではなくhttp ブロックに書く点に注意してください。

http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
}
要素 意味
$binary_remote_addr IPアドレス(バイナリ形式)
zone=mylimit:10m 状態を保存する共有メモリゾーン。名前(任意) mylimit、サイズ 10MB
rate=1r/s 許可するレート。1r/s は「1秒に1リクエスト」

limit_req

定義したゾーンを server または location ブロックに適用します。

server {
    ...
    location / {
        limit_req zone=mylimit burst=5 nodelay;
    }
}
パラメータ 意味
zone=mylimit 適用するゾーン名
burst=5 rateを超えた分を最大5件まで受け入れる
nodelay 待たせずに即時処理する(後述)

動かしてみる

実際に動かして挙動を確認します。

nginx.conf を用意

rate=1r/s(1秒に1リクエスト)という設定にします。

events {}

http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;

    server {
        listen 80;
        root /usr/share/nginx/html;

        location / {
            limit_req zone=mylimit;
        }
    }
}

Nginx起動

docker run --rm -d --name nginx-test \
  -p 8080:80 \
  -v$(pwd)/nginx.conf:/etc/nginx/nginx.conf” \
  nginx:latest

# 動作確認
curl -s -o /dev/null -w “%{http_code}\n” http://localhost:8080
# => 200

burst なしパターン

burst を指定しない場合、rate を超えた瞬間に拒否されます。

location / {
    limit_req zone=mylimit;
}

10本同時にリクエストを投げて確認します。

time (seq 10 | xargs -P 10 -I{} curl -s -o /dev/null -w “%{http_code}\n” http://localhost:8080 | sort)

結果

200
503
503
503
503
503
503
503
503
503
---- real 0.040 sec ----

1秒に1リクエストしか許可されないので即拒否されます。

burstありパターン

location / {
    limit_req zone=mylimit burst=5;
}
time (seq 10 | xargs -P 10 -I{} curl -s -o /dev/null -w “%{http_code}\n” http://localhost:8080 | sort)

結果

200
200
200
200
200
200
503
503
503
503
---- real 5.054 sec ----

通る本数が 1 → 6 に増えました(rate分の1本 + burst分の5本)。
また、注目すべきは完了までの時間です。burst だけだと、burst分の5本はすぐに処理されるのではなく rate(1秒に1本)のペースで順番に処理されるため、完了まで約5秒かかります。

burst + nodelayパターン

location / {
    limit_req zone=mylimit burst=5 nodelay;
}
time (seq 10 | xargs -P 10 -I{} curl -s -o /dev/null -w “%{http_code}\n” http://localhost:8080 | sort)

結果

200
200
200
200
200
200
503
503
503
503
---- real 0.039 sec ----

通る本数はburstありパターンと同じ6本ですが、待ち時間がほぼゼロになりました。
nodelay は burstを待たせるのではなく即座に処理します。消費した枠は rate のペースで少しずつ回復していきます。直後にもう一度叩くと、枠がまだ回復していないので拒否が増えるはずです。

# 上のテスト直後に実行すると200の数が減っている
time (seq 10 | xargs -P 10 -I{} curl -s -o /dev/null -w “%{http_code}\n” http://localhost:8080 | sort)

200
503
503
503
503
503
503
503
503
503
---- real 0.037 sec ----

参考

10
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?