Scaling your API with rate limiters

Bài tóm tắt Stripe 2017 2. Tăng trưởng Độ khó: Dễ

Stripe · 2017 · 2. Tăng trưởng · Độ khó: Dễ — bài gốc

Bối cảnh

  • Thêm capacity chỉ đỡ được mấy lần tăng traffic đầu; API production còn phải chống một người dùng (vô tình hay cố ý) làm ảnh hưởng mọi người, ưu tiên request quan trọng hơn request ít quan trọng, và bỏ bớt request khi bên trong có sự cố.
  • Phân biệt: rate limiter quyết theo người dùng (họ có thể giãn request mà không đổi kết quả); load shedder quyết theo trạng thái cả hệ, dùng khi khẩn cấp.

Thay đổi chính

  • Bốn loại chạy cùng nhau (số liệu một tháng năm 2017):
    1. Request rate limiter: N request/giây mỗi người dùng, quan trọng nhất, chặn hàng triệu request mỗi tháng (nhiều nhất là script test mode chạy quá tay); hành vi giống nhau ở test và live; cho phép burst ngắn cho sự kiện real-time (flash sale).
    2. Concurrent requests limiter: tối đa khoảng 20 request đang chạy cùng lúc; cho endpoint tốn CPU, nơi người dùng chờ lâu rồi retry làm quá tải thêm. Chặn khoảng 12.000 request/tháng; theo bài, giải quyết hẳn tranh chấp tài nguyên ở endpoint đắt nhất.
    3. Fleet usage load shedder: chia traffic thành quan trọng (tạo charge) và không quan trọng (liệt kê charge), đếm bằng Redis; luôn giữ một phần fleet (ví dụ 20%) cho loại quan trọng, loại kia vượt 80% thì trả 503.
    4. Worker utilization load shedder: lớp cuối, chỉ bật khi sự cố lớn (100 request bị chặn trong tháng). Bốn hạng: critical, POST, GET, test mode; worker bận thì bỏ dần từ test mode, chưa đủ thì leo thang. Bỏ và trả lại phải chậm, nếu không sẽ dao động; tốc độ chỉnh bằng thử sai, chọn mức bỏ được lượng lớn trong vài phút.
  • Cài đặt: token bucket mỗi người dùng một bucket, trên Redis. Lưu ý:
    • Gắn vào middleware an toàn: lỗi code hay Redis chết thì fail open, API vẫn chạy.
    • Lỗi rõ ràng cho người dùng (429 hay 503 tuỳ trường hợp), thông điệp hành động được.
    • Kill switch bằng feature flag, metric và alert về tần suất kích hoạt.
    • Dark launch từng limiter để xem nó sẽ chặn gì trước khi chặn thật; làm việc với khách để đổi code nếu cần.
  • Khuyến nghị: bắt đầu bằng request rate limiter, thêm ba loại kia khi quy mô cần.

Vì sao

  • Mỗi loại chặn một kiểu sự cố khác nhau: lạm dụng theo người dùng, tranh chấp ở endpoint đắt, request ít quan trọng chiếm chỗ request quan trọng, quá tải khi đang có sự cố.

Bài học cho SWE

  • Rate limit theo người dùng là phòng ngừa; load shedding theo trạng thái hệ là kiểm soát thiệt hại; cần cả hai.
  • Bộ bảo vệ không được thành điểm lỗi mới: fail open, có công tắc tắt, dark launch trước.
  • Giới hạn đồng thời đổi mô hình lập trình của client ("chia N worker xử lý hàng đợi" thay cho "dội API rồi lùi khi 429").

Liên quan