← Về danh sách
Mạng
#처리율제한#RateLimiting#토큰버킷#슬라이딩윈도우#API게이트웨이
Cập nhật lần cuối · 2026-09-16

Giới hạn tốc độ (Rate Limiting) và các thuật toán kiểm soát lưu lượng

1. Tổng quan

A. Định nghĩa

Giới hạn tốc độ (Rate Limiting) là kỹ thuật kiểm soát lưu lượng, kiểm soát số lượng yêu cầu mà một client·API·tài nguyên có thể thực hiện trong một cửa sổ thời gian (window) nhất định bằng một hạn mức (quota) định sẵn, và trì hoãn·từ chối·đệm phần vượt mức nhằm bảo đảm tính ổn định và công bằng của hệ thống.

Giới hạn tốc độ là chính sách điều khiển luồng quyết định cho phép yêu cầu "nhanh đến đâu, nhiều đến đâu". Khác với điều khiển tắc nghẽn ở tầng mạng vốn điều chỉnh tốc độ truyền đầu-cuối, giới hạn tốc độ chủ yếu nhận diện từng bên gọi ở tầng ứng dụng·API và điều tiết tần suất yêu cầu của bên gọi đó, nên mối quan tâm là khác nhau. Tức là đối tượng không phải gói tin mà là yêu cầu logic (yêu cầu HTTP, lời gọi RPC, thông điệp), và tiêu chí nhận diện là chủ thể có ý nghĩa nghiệp vụ như IP·khóa API·tài khoản người dùng·tenant.

Giới hạn tốc độ thường được dùng lẫn với "điều tiết (Throttling)" nhưng sắc thái khác nhau. Hiểu rộng, giới hạn tốc độ là chính sách phán định có vượt hạn mức hay không, còn throttling là cách thực thi xử lý yêu cầu (từ chối·trì hoãn·xếp hàng) khi đã xác nhận vượt mức. Do đó, hệ thống được thiết kế tốt sẽ thiết kế tách biệt "định nghĩa hạn mức (Rate Limiting)" và "hành vi khi vượt mức (Throttling)", và việc trả về HTTP 429 Too Many Requests cùng header Retry-After làm phản hồi vượt mức đã trở thành tiêu chuẩn trên thực tế.

B. Bối cảnh ra đời và sự cần thiết

Các dịch vụ hiện đại đã tiến hóa sang hình thức phơi bày giao diện ra bên ngoài như API công khai, open banking, MyData, API AI tạo sinh. Ngay khi giao diện được mở ra, dịch vụ đồng thời đối mặt với lượng gọi lớn thiện ý và sự lạm dụng ác ý. Ví dụ, nếu một client triển khai sai rơi vào vòng lặp thử lại và gọi hàng nghìn lần mỗi giây, hoặc một cuộc tấn công credential stuffing gõ vào API đăng nhập hàng chục nghìn lần mỗi giây, sẽ xảy ra suy giảm dịch vụ ảnh hưởng cả đến người dùng bình thường. Giới hạn tốc độ là tuyến phòng thủ tối thiểu dựng vách ngăn trong những tình huống như vậy để "một người dùng quá mức không thể độc chiếm toàn bộ tài nguyên".

Sự cần thiết thứ hai nằm ở tính hữu hạn của chi phí và tài nguyên. Trong môi trường đám mây, dù tự động mở rộng (autoscaling) có hấp thụ tải thì việc mở rộng cũng kéo theo độ trễ và chi phí. Đặc biệt, các backend có chi phí mỗi lần gọi lớn như suy luận AI tạo sinh hay thanh toán·quyết toán không thể mở rộng vô hạn, nên phải đặt giới hạn trên ngay ở giai đoạn yêu cầu đi vào để bảo vệ hạ nguồn. Khi đó, giới hạn tốc độ cùng với circuit breaker·bulkhead trở thành phương tiện cốt lõi để hiện thực "loại bỏ tải (Load Shedding)".

Sự cần thiết thứ ba là công bằng và kiếm tiền. Kinh doanh SaaS·API phân cấp mức dịch vụ bằng cách cấp hạn mức gọi khác nhau theo gói cước như Free·Pro·Enterprise. Chẳng hạn, một API LLM thương mại giới hạn đồng thời số yêu cầu mỗi phút (RPM) và số token mỗi phút (TPM) theo cấp gói cước, cho thấy giới hạn tốc độ đã vượt ra ngoài phòng thủ đơn thuần để trở thành trục của tính phí·SLA·thiết kế sản phẩm.

C. Mục tiêu áp dụng

Mục tiêu áp dụng gồm: thứ nhất, bảo vệ tính sẵn sàng (phòng thủ backend trước lưu lượng bùng nổ·DDoS·bão thử lại); thứ hai, phân bổ tài nguyên công bằng (cô lập giữa các tenant·người dùng); thứ ba, kiểm soát chi phí (giới hạn trên lượng gọi hạ nguồn); thứ tư, kiếm tiền·thực hiện SLA (hạn mức phân biệt theo cấp); thứ năm, cung cấp tín hiệu sơ cấp để phát hiện lạm dụng·hành vi bất thường. Năm mục tiêu này có thể mâu thuẫn nhau, nên việc lựa chọn thuật toán và cách triển khai phân tán sẽ bàn ở phần sau thay đổi tùy theo mục tiêu nào được ưu tiên.

2. Cấu trúc tổng thể và vị trí bố trí

Bộ giới hạn tốc độ đặt ở đâu trên đường đi của yêu cầu sẽ quyết định độ chính xác·hiệu năng·độ phức tạp vận hành. Sơ đồ khái niệm dưới đây cho thấy giới hạn tốc độ can thiệp tại những điểm nào trên đường đi của yêu cầu từ client tới backend.

flowchart LR
  C["Client(nhiều người dùng)"] --> E["Edge/CDN(phòng thủ L7)"]
  E --> G["API gateway(Rate Limiter)"]
  G -->|"Cho phép(thông qua)"| S["Dịch vụ backend"]
  G -->|"Vượt mức(trả về 429)"| R["Phản hồi từ chối(Retry-After)"]
  G <--> D[("Kho bộ đếm trung tâm(Redis, v.v.)")]
  S --> DB[("DB/API bên ngoài(đối tượng bảo vệ)")]

Cách bố trí phổ biến nhất là ở tầng API gateway·reverse proxy. Đây là cửa ngõ mà mọi yêu cầu bắt buộc phải đi qua, nên thuận lợi để áp dụng hạn mức ngay sau xác thực khi đã nhận diện được bên gọi. Gateway lọc yêu cầu trước khi phân nhánh tới nhiều backend nên có ưu điểm bảo vệ toàn bộ hạ nguồn cùng một lúc. Ngược lại, có hạn chế là khó phản ánh chi tiết đặc tính tài nguyên riêng của từng backend (ví dụ: một endpoint nặng cụ thể), nên trong thực tế thường dùng thiết kế kết hợp phân tầng hạn mức toàn cục ở gateway với hạn mức cục bộ bên trong dịch vụ.

Cách bố trí thứ hai là ở tầng middleware ứng dụng. Có thể đặt hạn mức theo đơn vị endpoint·chức năng ngay trong mã dịch vụ, cho phép kiểm soát chính xác theo đặc tính miền nghiệp vụ như "yêu cầu thanh toán 5 lần mỗi phút, truy vấn 300 lần mỗi phút". Tuy nhiên, khi dịch vụ mở rộng ra nhiều instance, phát sinh vấn đề phân tán là cộng gộp bộ đếm cục bộ của từng instance thế nào.

Cách bố trí thứ ba là ở tầng edge/CDN. Chặn sớm lưu lượng lớn ở mức CDN·WAF dựa trên tín hiệu IP·khu vực·bot giúp tiết kiệm chi phí trước khi tới origin và cấu thành phòng thủ theo chiều sâu (Defense in Depth). Độ chính xác thấp nhưng đóng vai trò tuyến phòng thủ đầu tiên rẻ nhất và nhanh nhất.

3. Các thuật toán giới hạn tốc độ

Các thuật toán được phân biệt theo "đếm thời gian và số lượng như thế nào", và mỗi loại có sự đánh đổi khác nhau về độ chính xác·cho phép bùng phát·bộ nhớ·độ khó triển khai. Sơ đồ kiến trúc chi tiết dưới đây đối chiếu nguyên lý hoạt động của bốn thuật toán tiêu biểu.

flowchart TB
  subgraph TB["Token bucket(Token Bucket)"]
    TBf["Nạp token với tốc độ cố định"] --> TBb["Bucket(giới hạn dung lượng)"]
    TBb --> TBr["Mỗi yêu cầu tiêu 1 token, hết thì từ chối"]
  end
  subgraph LB["Leaky bucket(Leaky Bucket)"]
    LBq["Nạp yêu cầu vào hàng đợi"] --> LBo["Xả(xử lý) với tốc độ cố định"]
    LBo --> LBd["Hàng đợi đầy thì loại bỏ"]
  end
  subgraph SW["Cửa sổ trượt(Sliding Window)"]
    SWl["Log/trọng số yêu cầu N giây gần nhất"] --> SWc["Phán định bằng tổng khoảng liên tục"]
  end

A. Token bucket (Token Bucket)

Token bucket là cách trong đó token được nạp vào bucket với tốc độ cố định (refill rate), mỗi yêu cầu khi được xử lý sẽ tiêu một token, và nếu không còn token thì bị từ chối. Bucket có dung lượng tối đa (capacity) nên token không tích tụ vượt quá mức đó. Ưu điểm cốt lõi của cấu trúc này là cho phép bùng phát (tăng vọt tức thời). Nếu bình thường yêu cầu ít và token đã tích đầy dung lượng, có thể xử lý cùng lúc các yêu cầu dồn đến đột ngột. Ví dụ, bucket có dung lượng 100, tốc độ nạp 10 token mỗi giây sẽ duy trì trung bình 10 yêu cầu mỗi giây, nhưng hấp thụ tức thời tới 100 yêu cầu nhờ 100 token tích lũy trong thời gian nhàn rỗi. Do đó nó phù hợp với các API tương tác đề cao cảm nhận người dùng (tìm kiếm·tự động hoàn thành), và thực tế nhiều API gateway và API đám mây chọn làm thuật toán mặc định. Nhược điểm là phải tinh chỉnh đồng thời hai tham số dung lượng và tốc độ, và nếu cho phép bùng phát quá mức thì hạ nguồn có thể chịu tải tức thời.

B. Leaky bucket (Leaky Bucket)

Leaky bucket là cách đưa yêu cầu vào hàng đợi (bucket) và chỉ lấy ra xử lý (rò rỉ) với tốc độ cố định, khi hàng đợi đầy thì loại bỏ các yêu cầu tiếp theo. Nếu token bucket xuất phát từ ý tưởng "tích lũy trước lượng cho phép", thì leaky bucket xuất phát từ ý tưởng "cố định tốc độ đầu ra một cách bằng phẳng". Do đó lưu lượng đầu ra được định hình mượt mà (traffic shaping), có lợi khi phía sau đòi hỏi tốc độ xử lý cố định (ví dụ: mạng thanh toán bên ngoài chỉ nhận số giao dịch nhất định mỗi giây, bên tiêu thụ của message broker). Ngược lại, vì không hấp thụ được bùng phát nên các yêu cầu hợp lệ dồn đến sau thời gian nhàn rỗi cũng có thể chịu trễ hàng đợi hoặc bị loại bỏ, nên ít phù hợp với dịch vụ tương tác. Về triển khai, leaky bucket thực chất được hiện thực bằng hàng đợi FIFO dung lượng cố định + bên tiêu thụ tốc độ đều, và có đánh đổi là khi độ trễ tích tụ thì thời gian phản hồi tăng.

C. Bộ đếm cửa sổ cố định (Fixed Window Counter)

Cửa sổ cố định là cách đơn giản nhất: đặt bộ đếm cho mỗi cửa sổ thời gian có biên cố định như "giây 0~59 của mỗi phút", và đặt lại về 0 khi chuyển cửa sổ. Bộ nhớ chỉ cần một bộ đếm nên cực kỳ nhẹ và dễ triển khai. Tuy nhiên, nó có điểm yếu chí mạng gọi là bùng phát tại biên (boundary burst). Khi hạn mức là 100 yêu cầu mỗi phút, nếu một người dùng gửi 100 yêu cầu lúc 12:00:59 và lại 100 yêu cầu lúc 12:01:00 thì 200 yêu cầu lọt qua trong khoảng hơn 1 giây. Tức là tại biên của cửa sổ có thể tức thời cho phép gấp đôi hạn mức, nên không phù hợp với các endpoint nhạy cảm cần giới hạn trên chặt chẽ như thanh toán·xác thực.

D. Cửa sổ trượt (Sliding Window)

Cửa sổ trượt đánh giá liên tục "N giây gần nhất tính từ thời điểm hiện tại" để giải quyết vấn đề biên của cửa sổ cố định. Dạng chính xác là sliding window log, lưu dấu thời gian của từng yêu cầu và khi phán định thì đếm số log thuộc N giây gần nhất. Cách này chính xác nhưng phải lưu dấu thời gian cho mỗi yêu cầu nên tốn nhiều bộ nhớ. Phương án thỏa hiệp được dùng rộng rãi trong thực tế là sliding window counter, xấp xỉ bằng trung bình có trọng số giữa bộ đếm của cửa sổ hiện tại và cửa sổ liền trước. Chẳng hạn, nếu tỷ lệ thời gian đã trôi qua của cửa sổ hiện tại là 30% thì ước lượng bằng số_đếm_cửa_sổ_trước × 0.7 + số_đếm_cửa_sổ_hiện_tại, bộ nhớ chỉ cần hai bộ đếm mà vẫn giảm đáng kể bùng phát tại biên. Cân bằng giữa độ chính xác và tài nguyên tốt nên được các CDN·API gateway xử lý lưu lượng lớn ưa chuộng.

Bảng dưới đây so sánh đặc tính của bốn thuật toán. Bảng chỉ nhằm hỗ trợ tóm tắt, còn căn cứ lựa chọn nằm ở phần giải thích đánh đổi trong văn xuôi ở trên.

Thuật toán Cho phép bùng phát Độ chính xác Bộ nhớ Ứng dụng tiêu biểu
Token bucket Cao (phần tích lũy) Trung bình Thấp API tương tác, mặc định của gateway
Leaky bucket Thấp (làm phẳng) Trung bình Trung bình Định hình lưu lượng, tiêu thụ tốc độ đều
Cửa sổ cố định Quá mức tại biên Thấp Rất thấp Giới hạn đơn giản·rủi ro thấp
Cửa sổ trượt Thấp Cao Trung bình Giới hạn chính xác, API quy mô lớn

4. Triển khai trong môi trường phân tán

Khi instance dịch vụ mở rộng lên hàng chục máy, nảy sinh vấn đề căn bản "hạn mức là toàn cục nhưng bộ đếm lại phân tán". Nếu mỗi instance chỉ dùng bộ đếm cục bộ thì hạn mức bị thổi phồng theo số instance, ngược lại nếu hỏi kho trung tâm cho mỗi yêu cầu thì độ trễ và tải tăng lên. Do đó, giới hạn tốc độ phân tán là thiết kế thỏa hiệp giữa độ chính xác và hiệu năng.

Cách triển khai phổ biến nhất là đặt bộ đếm ở kho trung tâm (Redis). Dùng lệnh nguyên tử của Redis (INCR, EXPIRE) hoặc Lua script để xử lý "tăng và hết hạn cùng một lúc" nhằm loại bỏ tranh chấp, và nhiều instance chia sẻ cùng một khóa (ví dụ: rate:user:1234:minute) để áp đặt hạn mức toàn cục. Cách này chính xác nhưng kho có thể trở thành điểm lỗi đơn lẻ, nên phải xác định bằng chính sách rằng khi kho gặp sự cố sẽ chặn yêu cầu (fail-closed) hay cho qua (fail-open). Dịch vụ ưu tiên tính sẵn sàng thường chọn fail-open, nhưng các đường có rủi ro lạm dụng lớn như xác thực·thanh toán thì đặt fail-closed.

Nếu hiệu năng quan trọng thì dùng xấp xỉ cục bộ + đồng bộ định kỳ. Mỗi instance phán định nhanh tại chỗ, và ở chế độ nền báo cáo·điều chỉnh mức sử dụng với trung tâm; đổi lại chấp nhận vượt mức chút ít để có độ trễ thấp. Cách này phù hợp khi không cần giới hạn trên toàn cục chính xác mà bảo vệ gần đúng là đủ.

Điểm thực tiễn cần lưu ý ở đây là thông báo minh bạch trạng thái giới hạn tốc độ cho client. Phơi bày hạn mức còn lại qua các header X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, và khi vượt mức trả về 429 cùng Retry-After, thì client có thể hợp tác bằng backoff lũy thừa, ngăn ngừa bão thử lại.

5. Chuyên sâu — Xu hướng tiêu chuẩn hóa và tình huống ứng dụng thực tiễn

Trong thời gian dài, giới hạn tốc độ có tên header và định dạng phản hồi khác nhau tùy nhà cung cấp, nên khả năng tương tác của client thấp. Để cải thiện điều này, IETF đã tiến hành tiêu chuẩn hóa đặc tả phơi bày thông tin giới hạn tốc độ bằng header chuẩn (họ RateLimit/RateLimit-Policy), và các trường chi tiết vẫn đang được sửa đổi nên khi triển khai nên kiểm tra bản thảo mới nhất. Mục đích của tiêu chuẩn hóa là để các dịch vụ khác nhau thông báo hạn mức còn lại·thời điểm đặt lại theo cùng định dạng, giúp SDK và gateway thực hiện backoff một cách nhất quán.

Về tình huống thực tiễn, thứ nhất là tính phí theo cấp của các nền tảng API công khai. Các nhà cung cấp đám mây·SaaS cấp hạn mức gọi mỗi giây·mỗi phút theo gói cước, và khi vượt mức thì trả về 429 hoặc linh hoạt hóa bằng tính phí bổ sung (tín dụng bùng phát). Thứ hai, API AI tạo sinh áp dụng kép hạn mức số yêu cầu (RPM) và hạn mức số token (TPM). Cùng số yêu cầu nhưng chi phí tính toán thực tế khác nhau lớn tùy độ dài prompt, nên đây là ví dụ cho thấy đặt hạn mức trên đơn vị tiêu thụ tài nguyên thực tế (token) là hợp lý. Thứ ba, các endpoint xác thực như đăng nhập·OTP·đặt lại mật khẩu áp giới hạn cửa sổ trượt chặt chẽ theo IP·tài khoản để làm chậm credential stuffing·tấn công vét cạn (brute force), đây là điểm giới hạn tốc độ tiếp xúc trực tiếp với kiểm soát bảo mật.

Về hướng tương lai, sự chuyển dịch từ hạn mức tĩnh sang giới hạn tốc độ thích ứng (adaptive) đang được chú ý. Đây là cách quan sát các tín hiệu tải như độ trễ·tỷ lệ lỗi·độ dài hàng đợi theo thời gian thực của backend để điều chỉnh hạn mức động, kết hợp với circuit breaker·loại bỏ tải·tự động mở rộng để hệ thống tự tìm điểm ổn định. Nó có thể nâng tỷ lệ sử dụng tài nguyên cao hơn hạn mức cố định theo tỷ lệ đều, nhưng nếu vòng điều khiển không ổn định có thể phát sinh dao động (oscillation), nên khả năng quan sát và tinh chỉnh thận trọng là tiền đề.

6. Các điểm cần cân nhắc và hàm ý

  • Tính chính xác trong thiết kế đối tượng hạn mức và khóa: Tiêu chí IP gộp nhiều người dùng sau NAT·proxy thành một khối và gây phát hiện sai, còn tiêu chí người dùng·khóa API chỉ khả dụng sau xác thực. Do đó, cần thiết kế khóa đa chiều: đoạn chưa xác thực dùng IP·dấu vân tay thiết bị, đoạn đã xác thực dùng khóa tài khoản·tenant theo phân tầng, và đặt hạn mức khác nhau theo độ nhạy của endpoint (truy vấn vs thanh toán).
  • Căn chỉnh đánh đổi giữa thuật toán·vị trí bố trí: Lưu lượng tương tác cần cho phép bùng phát thì dùng token bucket, hạ nguồn cần xử lý tốc độ đều thì dùng leaky bucket, API nhạy cảm cần giới hạn trên chặt chẽ thì dùng cửa sổ trượt. Phải kết hợp phân tầng: bảo vệ toàn cục ở gateway, kiểm soát chính xác bên trong dịch vụ.
  • Nêu rõ chính sách sự cố (fail-open vs fail-closed): Phải quyết định trước sẽ ưu tiên điều gì khi kho bộ đếm gặp sự cố. Dịch vụ ưu tiên sẵn sàng dùng fail-open, đường có rủi ro lạm dụng·chi phí lớn dùng fail-closed, và trong cả hai trường hợp đều chuẩn bị cảnh báo cùng phương án dự phòng (giới hạn xấp xỉ cục bộ).
  • Liên kết khả năng quan sát với phát hiện lạm dụng: Chỉ số hóa tỷ lệ phát sinh 429, người dùng gần chạm hạn mức, phân bố tiêu thụ theo khóa giúp tận dụng cho hoạch định dung lượng và phát hiện hành vi bất thường. Log giới hạn tốc độ trở thành đầu vào có ý nghĩa cho SIEM·phát hiện bất thường, vượt ra ngoài phòng thủ đơn thuần để làm nguồn tín hiệu cho bảo mật·vận hành.
  • Kết hợp với các mẫu khả năng phục hồi (resilience): Giới hạn tốc độ không tự hoàn chỉnh một mình. Chỉ khi được thiết kế cùng circuit breaker (chặn lan truyền sự cố), bulkhead (cô lập tài nguyên), thử lại·backoff lũy thừa (thử lại hợp tác), loại bỏ tải (ưu tiên loại bỏ yêu cầu ưu tiên thấp) thì hệ thống mới chịu được lưu lượng bùng nổ và sự cố.

Tài liệu tham khảo


Tóm tắt một câu: Giới hạn tốc độ là kỹ thuật kiểm soát lưu lượng giới hạn số yêu cầu trong một cửa sổ thời gian theo hạn mức, chọn thuật toán token bucket·leaky bucket·cửa sổ cố định/trượt phù hợp tình huống và triển khai phân tán qua gateway·kho trung tâm để đồng thời bảo đảm tính sẵn sàng·công bằng·chi phí·bảo mật.