iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0

前面我們已經加入 Load Balancer、Cache、Database
Replication、Sharding、CDN、Message Queue。

但如果某個 Client 突然送出:

100,000 Requests/sec

原因可能是 Bot、Buggy Client、Crawler、Malicious User 或 Traffic
Spike。即使 Backend 可以 Scale,系統仍可能被壓垮。

今天要解決:

一個 User / Client 在一段時間內,到底可以呼叫 API 幾次?

答案就是 Rate Limiter。


Rate 是什麼?

Rate 是某件事情在一段時間內發生多少次。

100 requests / second
= 100 req/s

Request Rate 就是 Client 在一段時間內送出多少 Requests。

User A → 2 req/s
User B → 10 req/s
Bot    → 10,000 req/s

Threshold 是什麼?

Threshold 是限制值 / 門檻。

例如:

100 requests / minute

第 1~100 個 Request 可以 Allow,第 101 個就可能 Reject。


Rate Limiter 是什麼?

Rate Limiter:

限制某個 Client 在特定時間內可以執行多少次操作的機制。

User
 ↓
Rate Limiter
 ↓
Allowed?
 ├── Yes → Backend
 └── No  → Reject

常見目的:

Protect Backend
Protect Database
Prevent Abuse
Control Cost
Fair Usage
Prevent Brute Force

HTTP 429 是什麼?

超過限制時,Server 常回:

HTTP 429 Too Many Requests

200 → Success
404 → Not Found
500 → Server Error
429 → Too Many Requests

API 還可能回 Retry-After,告訴 Client 多久後再嘗試。


Rate Limit 要限制誰?

可以根據:

IP Address
User ID
API Key
Device
Endpoint
Organization
Subscription Plan

例如:

Free User    → 100 requests/hour
Premium User → 10,000 requests/hour

只用 IP 也有缺點:公司或學校的很多 User 可能共用同一 Public IP。因此
Rate Limit Key 的選擇本身也是 Trade-off。


Fixed Window

Fixed Window 是把時間切成固定區間,每個區間計算 Request 次數。

Limit = 100 requests/minute

12:00:00 ~ 12:00:59 → Window #1
12:01:00 ~ 12:01:59 → Window #2

每個 Window 有一個 Counter。

Counter 就是記錄次數的數值:

User 123
Count = 47

下一個 Request:

47 → 48

超過 Limit 就 Reject。


Fixed Window 的 Boundary Problem

假設:

Limit = 100 requests/minute

User 在:

12:00:59 → 100 Requests
12:01:00 → 100 Requests

兩個 Window 都合法,但約 1 秒內可能通過 200 Requests。

這就是:

Boundary Problem


Burst 是什麼?

Burst 是短時間突然出現大量 Traffic。

Normal → 100 req/s
Burst  → 10,000 req/s

Rate Limiter 的重要目的之一就是控制 Burst 對系統的壓力。


Sliding Window

Sliding Window 不只看固定分鐘,而是從「現在」往前看一段時間。

例如現在:

12:01:30

一分鐘 Sliding Window 看:

12:00:30 ~ 12:01:30

而不是只看:

12:01:00 ~ 12:01:59

Sliding Window Log

一種方法是保存每個 Request 的 Timestamp(發生時間點)。

收到新 Request:

1. 移除 Window 外的 Timestamp
2. 計算剩下多少 Requests
3. 低於 Limit → Allow
4. 否則 → Reject

優點:

Accurate

缺點:

Need More Memory

所以又是 Accuracy vs Cost 的 Trade-off。


Token Bucket

Token Bucket 可以想像一個裝 Token 的桶子。

每個 Request:

需要 1 Token

有 Token:

Allow

沒有:

Reject / Wait

例如:

Capacity = 10 Tokens
Refill Rate = 2 Tokens/sec

一開始有 10 Tokens,突然來 8 Requests,可以直接通過。之後每秒再補 2
Tokens。

所以 Token Bucket:

允許一定程度的短時間 Burst,但控制長期平均速度。


Leaky Bucket

Leaky Bucket 像一個會漏水的桶子:

Incoming Requests
      ↓
    Bucket
      ↓
Fixed Output Rate

即使瞬間進來很多 Requests,也用較穩定的速度往外處理。

簡化比較:

Token Bucket
→ Allows some burst

Leaky Bucket
→ Smooths traffic

Rate Limiter 放在哪裡?

如果放在 Backend 裡:

User → Backend → Rate Limiter

Request 已經消耗部分 Backend Resource。

因此常希望更早處理:

User
 ↓
API Gateway
 ↓
Rate Limiter
 ↓
Backend

API Gateway 是什麼?

API Gateway 可以理解成:

Client 進入 Backend APIs 前的統一入口。

Client
 ↓
API Gateway
 ├── /users  → User Service
 ├── /orders → Order Service
 └── /pay    → Payment Service

它常處理:

Authentication
Routing
Rate Limiting
Logging

Reverse Proxy 是什麼?

Reverse Proxy 是站在 Server 前面,先接 Client Request,再轉送到後方
Server 的 Component。

Client
 ↓
Reverse Proxy
 ↓
Backend

它可能提供 Routing、TLS Termination、Load Balancing、Caching、Rate
Limiting。


Distributed Rate Limiting

如果有:

Backend #1
Backend #2
Backend #3

Limit 是:

100 requests/minute

User 被分散:

Backend #1 → 50
Backend #2 → 50
Backend #3 → 50

每台都認為沒超過 100,但 User 實際送了:

150 Requests

這就是 Distributed Rate Limiting Problem。


為什麼 Redis 常被使用?

多台 Backend 需要 Shared Counter:

Backend #1 ─┐
Backend #2 ─┼→ Redis
Backend #3 ─┘

Redis:

rate:user:123 = 87

所有 Server 看到同一份 Rate Limit State。


Atomic Operation 是什麼?

假設兩台 Server 同時看到:

Count = 99

如果都做:

GET → +1 → SET

可能產生錯誤。

Atomic Operation 可以理解成:

一個操作在系統看起來像不可拆開的一個完整動作。

Redis 的:

INCR rate:user:123

可以用 Atomic Increment 避免簡單的 Counter Race。


Race Condition 是什麼?

Race Condition:

多個 Request / Thread 同時操作 Shared Data,結果受到執行順序影響。

Count = 99

Server A reads 99
Server B reads 99

A writes 100
B writes 100

理論上應該 101,最後卻可能只有 100。

所以 Distributed Rate Limiter 還要考慮:

Concurrency
Atomicity

Redis Counter + Expiration

Fixed Window 可以概念化成:

Key:
rate:user:123:12:00

Value:
57

並設定 Expiration。

流程:

INCR
 ↓
Count <= Limit?
 ├── Yes → Allow
 └── No  → 429

實作時還要注意 INCR 與 Expiration 等多個操作之間的 Failure / Atomicity
問題。


Rate Limiter 掛掉怎麼辦?

假設 Rate Limiter 的 Store 掛掉:

Redis ❌

現在要:

全部 Allow?
全部 Reject?

這就是:

Fail Open vs Fail Closed

Fail Open

Rate Limiter Failure 時仍 Allow。

優點:

Availability Higher

缺點:

Backend loses protection

Fail Closed

Failure 時 Reject。

優點:

Protect Backend / Security

缺點:

Normal Users may be rejected

沒有永遠正確答案,要看 Business Requirement 與 Risk。


Rate Limiting vs Load Balancing

Load Balancer
→ Distribute Traffic

Rate Limiter
→ Control Traffic

Load Balancer 決定 Request 去哪台 Server;Rate Limiter 決定 Request
能不能進來。


Rate Limiting vs Message Queue

Message Queue
→ Accept work and process later

Rate Limiter
→ Reject / delay excessive traffic

例如:

API Abuse → Rate Limiter
Background Traffic Burst → Message Queue

Per-Endpoint Rate Limit

不同 API 成本不同:

GET /products
→ 1000 req/min

POST /login
→ 10 req/min

POST /generate-ai-report
→ 5 req/min

這叫:

Per-Endpoint Rate Limiting

AI API 甚至可以做 Cost-based Limiting:

GET /profile → 1 token
Generate AI Report → 20 tokens

不只計算 Request 數,也考慮 Request Cost。


台積 IT 面試情境:Login API 被打爆

如果 Login API 遭大量 Password Guessing:

可以考慮:

Per IP Limit
+
Per Account Limit

例如:

Per IP      → 20 attempts/min
Per Account → 5 attempts/min

只限制 IP,Attacker 可能換 IP;只限制 Account,也可能攻擊大量不同
Account。

所以可能需要多層 Policy。


台積面試延伸:多台 Backend

如果 10 台 Backend 每台各自限制:

100 req/min

User 經 Load Balancer 分散後,總量可能遠超 100。

因此需要:

Shared State

例如 Redis,再繼續思考:

Atomic Counter
Redis Availability
Network Latency
Fail Open / Closed

Rate Limiter 自己也可能變 Bottleneck

如果:

1,000,000 Requests/sec

每個 Request 都要查 Redis,Redis 也可能成為 Bottleneck。

可能進一步考慮:

Redis Cluster
Sharding
Local State
Multiple Rate Limiter Nodes
Approximate Counters

再次證明:

解決一個 Bottleneck,可能創造下一個 Bottleneck。


Retry-After 與 Backoff

收到:

429 Too Many Requests

Client 不應立即瘋狂 Retry。

Server 可以提供:

Retry-After

Client 則搭配 Day 11 的:

Exponential Backoff

讓 Retry 更平滑。


System Design Architecture 再進化

User
 ↓
CDN
 ↓
API Gateway
 ↓
Rate Limiter
 ↓
Load Balancer
 ↓
Backend
 ├── Redis
 ├── Database
 └── Message Queue

Rate Limiter 的核心角色:

在昂貴工作發生之前先保護系統。


台積 IT 面試準備 Checkpoint

1. Rate / Request Rate 是什麼?
2. Threshold 是什麼?
3. Rate Limiter 是什麼?
4. HTTP 429 是什麼?
5. Rate Limit 可以根據哪些 Key?
6. IP-based Limiting 有什麼問題?
7. Fixed Window 是什麼?
8. Boundary Problem 是什麼?
9. Burst Traffic 是什麼?
10. Sliding Window 是什麼?
11. Sliding Window Log 的 Trade-off?
12. Token Bucket 是什麼?
13. Token Bucket 為什麼允許 Burst?
14. Leaky Bucket 是什麼?
15. Token Bucket vs Leaky Bucket?
16. API Gateway 是什麼?
17. Reverse Proxy 是什麼?
18. Distributed Rate Limiting 是什麼?
19. 多台 Backend 各自計數為什麼有問題?
20. 為什麼 Redis 適合 Shared Counter?
21. Atomic Operation 是什麼?
22. Race Condition 是什麼?
23. Fail Open 是什麼?
24. Fail Closed 是什麼?
25. Fail Open vs Fail Closed 怎麼選?
26. Rate Limiting vs Load Balancing?
27. Rate Limiting vs Message Queue?
28. Per-Endpoint Rate Limit?
29. Login API 被 Password Guessing 怎麼設計?
30. Rate Limiter 自己成為 Bottleneck 怎麼辦?
31. Retry-After 是什麼?
32. Client 為什麼要使用 Backoff?

今天學到了什麼?

Rate Limiter 核心:

Request
 ↓
Identify Client
 ↓
Check Rate
 ↓
Within Limit?
 ├── Yes → Allow
 └── No  → Reject / Throttle

常見 Algorithm:

Fixed Window
Sliding Window
Token Bucket
Leaky Bucket

Distributed System 還要考慮:

Shared Counter
Atomicity
Race Condition
Redis Availability
Fail Open / Fail Closed

最重要的一句:

Rate Limiter 的目的不是單純拒絕 User,而是在有限的 System Capacity
下控制 Traffic,保護 Backend、Database 與其他昂貴資源。


下一篇

現在我們有很多 Distributed Components:

Backend Servers
Cache
Database Replicas
Database Shards
CDN
Message Queue
Rate Limiter

但不同 Server 上的資料:

不一定在同一時間完全相同

例如 Day 8:

Primary → Wei-Hong
Replica → Alvin

Replica 因 Replication Lag 還沒更新。

下一篇:

Day 13|Consistency:為什麼 Distributed System 有時會讀到舊資料?

會先從零解釋:

State
Consistency
Strong Consistency
Eventual Consistency
Stale Read
Read-After-Write Consistency

再用 User Profile、Social Media Like Count、Shopping Cart、Bank Balance
比較不同 Consistency Requirement。


上一篇
# Day 11|Message Queue:為什麼大型系統不把所有工作都塞在同一個 Request?
下一篇
# Day 13|Consistency:為什麼 Distributed System 有時會讀到舊資料?
系列文
30 天從 Full-Stack Engineer 進化到 System Design:從 0 設計可支撐百萬使用者的系統 共 15 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言