---
title: "レートを制限する"
language: "ja"
documentation_version: "3.x"
channel: "development"
release_context: null
source_revision: "10297d1e28653321d6996609fc53718d3b7c8278"
working_tree_clean: true
source_path: "docs/ja/guides/rate-limit.md"
source_sha256: "ff6a050fdf9b869047e41c6d5088c9d2d6d120d510cb2d3042592fb7462ded29"
source_at_revision: true
source_url: "https://github.com/matsumotory/ngx_mruby/blob/10297d1e28653321d6996609fc53718d3b7c8278/docs/ja/guides/rate-limit.md"
html_url: "https://ngx.mruby.org/ja/guides/rate-limit/"
markdown_url: "https://ngx.mruby.org/markdown/ja/guides/rate-limit.md"
last_updated: "2026-10-29"
---

# レートを制限する

nginxの`limit_req`は、すべてのワーカーが使う共有メモリのゾーンで、キーごとにリクエストを数え、レートを超えたリクエストを拒否します。キーには、nginxのどの変数でも使えます。Rubyのスクリプトが[`mruby_set`](/ja/reference/directives/#mruby_set-and-mruby_set_code)でキーを計算すれば、APIキーのような、Rubyがリクエストから取り出した値ごとに制限をかけられます。カウンタはnginxが持ちます。

## サンプル

スクリプトは、リクエストヘッダ`X-API-Key`のAPIキーを返します。ヘッダの無いリクエストではクライアントのアドレスを返します。こうして、どのリクエストもキーが空になりません。`limit_req`は、キーが空のリクエストを数えないからです。ゾーンは、キーごとに1分に1リクエストを許します。nginxは、`limit_req_status 429`と`error_page 429 @limited`に従って、拒否したリクエストのレスポンスをステータス429とJSONのボディにします。

```nginx title="test/conf/conf.d/75-guide-rate-limit.conf"
limit_req_zone $api_key zone=api_keys:1m rate=1r/m;

server {
    listen 18166;

    location /api/ {
        mruby_set $api_key build/nginx/html/guide_rate_limit.rb;
        limit_req zone=api_keys;
        limit_req_status 429;
        error_page 429 @limited;
        mruby_content_handler_code 'Nginx.rputs "accepted\n"';
    }

    location @limited {
        default_type application/json;
        return 429 '{"error":"rate_limited"}\n';
    }
}
```

```ruby title="test/html/guide_rate_limit.rb"
r = Nginx::Request.new
key = r.headers_in["X-API-Key"].to_s
key.empty? ? "addr:#{r.var.remote_addr}" : "key:#{key}"
```

```http title="test/html/guide_rate_limit.request：ケースが送るリクエスト"
GET /api/orders HTTP/1.1
Host: 127.0.0.1:18166
X-API-Key: demo-key
Connection: close
```

```http title="test/html/guide_rate_limit.response：ケースが比べるレスポンス"
HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{"error":"rate_limited"}
```

<p class="caption sample-caption">CIが動くたびに、ケースの<code>test/t/cases/guides.rb</code>がこのリクエストを送ります。ケースは、ステータス行、ここに載せたヘッダ、ボディ全体を比べます。<span class="nowrap">5個</span>のファイルを最後に変えたのは、<span class="nowrap">2026-10-29</span>のコミット<span class="nowrap"><code>32219e53</code>です。</span></p>

ケースはリクエストを2回送ります。1回目のレスポンスは、ボディが`accepted`の200です。同じ1分のうちに送った2回目のリクエストには、上のレスポンスが返ります。

## 気をつけること

- `mruby_set`はrewriteフェーズで動き、`limit_req`はその後のpreaccessフェーズで動きます。そのため、nginxがリクエストを数えるときには、変数に値が入っています。フェーズの順は[リクエストのフェーズ](/ja/concepts/request-phases/)にあります。
- カウンタは、Rubyではなくnginxの共有メモリのゾーンにあります。各ワーカーは自分の`mrb_state`を持つので、Rubyのグローバル変数のカウンタでは、1つのワーカーのリクエストしか数えられません。
- `limit_req_zone`は`http`ブロックのディレクティブです。`limit_req`と`limit_req_status`は、`http`ブロック、`server`、`location`に書けます。
