Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 7 — Rate Limiting & chống lạm dụng: bảo vệ hệ thống khỏi quá tải

Đã đọc 0/8 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

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-After cho 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