Guardrail nội dung và ngân sách bảo vệ từng request; rate limiting bảo vệ toàn hệ thống khỏi bị dồn dập — do người dùng lạm dụng, do bot, hoặc do chính agent gọi tool/API downstream quá nhanh. Bài này xây tầng rate limit thực dụng.
Ba mặt trận cần rate limit
- Người dùng → agent: một user (hoặc IP) spam request, làm cạn quota chung và đội chi phí.
- Agent → LLM provider: gọi model vượt TPM/RPM của nhà cung cấp → bị 429, hoặc đốt quota chia sẻ.
- Agent → tool/API downstream: agent gọi API đối tác (email, thanh toán, search) quá nhanh → bị chặn hoặc tính phí cao.
Thuật toán nền tảng: Token Bucket
Token bucket cho phép "bùng nổ" ngắn nhưng giữ tốc độ trung bình trong giới hạn — phù hợp cho agent (thỉnh thoảng cần vài call liên tiếp).
import time
class TokenBucket:
def __init__(self, capacity, refill_per_sec):
self.capacity = capacity # số token tối đa (burst)
self.refill = refill_per_sec # tốc độ hồi phục
self.tokens = capacity
self.ts = time.monotonic()
def allow(self, cost=1) -> bool:
now = time.monotonic()
self.tokens = min(self.capacity, self.tokens + (now - self.ts) * self.refill)
self.ts = now
if self.tokens >= cost:
self.tokens -= cost
return True
return False
# Ví dụ: mỗi user tối đa burst 10, hồi 1 request/giây
user_buckets = {}
def check_user(user_id):
b = user_buckets.setdefault(user_id, TokenBucket(10, 1))
if not b.allow():
raise RateLimited("Bạn thao tác quá nhanh, thử lại sau giây lát.")
Trong production, dùng bộ đếm chia sẻ (Redis) để rate limit đúng khi có nhiều tiến trình/server.
Xử lý giới hạn của LLM provider
Provider trả 429 Too Many Requests. Đừng retry ngay lập tức — hãy exponential backoff + jitter và tôn trọng header Retry-After:
import random, time
def call_with_backoff(fn, max_retry=5):
for i in range(max_retry):
try:
return fn()
except RateLimitError as e:
wait = getattr(e, "retry_after", None) or (2 ** i)
time.sleep(wait + random.uniform(0, 0.5)) # jitter tránh "thundering herd"
raise Exception("Hết lượt retry")
Các bước triển khai rate limit
- Chọn khóa giới hạn: theo user, theo API key, theo IP, theo tenant — thường kết hợp nhiều tầng.
- Đặt hạn mức: RPM/TPM hợp lý dựa trên hành vi bình thường + đệm an toàn.
- Dùng token bucket (cho phép burst) hoặc sliding window; lưu bộ đếm ở Redis khi đa tiến trình.
- Giới hạn concurrency: số agent chạy song song và số call downstream đồng thời (semaphore/queue).
- Backoff + jitter cho 429 từ provider; tôn trọng
Retry-After. - Circuit breaker: nếu downstream lỗi liên tục, ngắt tạm để không dồn thêm tải.
- Trả lỗi thân thiện cùng
Retry-Aftercho client, kèm log để phát hiện lạm dụng.
Khung phân tầng giới hạn
Tầng 1 Per-IP → chặn bot/scanner thô
Tầng 2 Per-user → chống một người lạm dụng
Tầng 3 Per-tenant → công bằng giữa khách hàng
Tầng 4 Global/provider→ không vượt quota LLM/API tổng
Checklist rate limiting
- [ ] Có giới hạn per-user và per-IP chưa?
- [ ] Bộ đếm có chia sẻ giữa các server (Redis) không, hay mỗi node đếm riêng (sai)?
- [ ] Có backoff + jitter cho 429 không?
- [ ] Có giới hạn concurrency cho call downstream không?
- [ ] Có circuit breaker khi downstream sập không?
- [ ] Lỗi rate limit có kèm Retry-After và được log không?
Sai lầm thường gặp
- Retry ngay lập tức khi 429. Làm tình hình tệ hơn (thundering herd). Luôn backoff + jitter.
- Đếm rate limit trong bộ nhớ mỗi node. Có 5 server thì hạn mức thực tế gấp 5 → vô nghĩa. Dùng store chia sẻ.
- Chỉ giới hạn đầu vào, quên downstream. Agent vẫn có thể spam API đối tác và bị phạt/chặn.
- Không có circuit breaker. Downstream chậm/sập, agent vẫn dồn request, kéo sập cả chuỗi.
- Hạn mức cứng nhắc quá thấp. Chặn nhầm người dùng thật. Đặt theo dữ liệu hành vi và cho phép burst hợp lý.
- Không phân biệt user thật và bot. Nên có tầng per-IP để chặn scanner trước khi tới tầng đắt tiền hơn.
Học xong bài này rồi?
Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu,
và học hết khóa thì có chứng chỉ.
Lưu tiến độ của tôi