RESTful: Phần 4 - API Rate Limiting

Rate limits có nhiều cách thực hiện khác nhau, chúng ta có thể xây dựng ở phía web-server hay web-app huặc cả hai, có thể sử dụng một huặc kết hợp nhiều loại với nhau, điều này còn phụ thuộc vào từng nhu cầu thực tế


10 min read
RESTful: Phần 4 - API Rate Limiting

Nội dung

  1. Rate Limiting

  2. Các lợi ích của rate limiting

  3. Các loại rate limits:
    3.1. User rate limiting:
    3.2. Geographic rate limiting:
    3.3. Server rate limiting:

  4. Một số thuật toán phổ biến
    4.1. Leaky bucket
    4.2. Fixed Window
    4.3. Sliding Window

  5. Thiết kế rate-limiting

  6. Triển khai API Rate Limiting


Rate Limiting

Ngoài việc đảm bảo performance của hệ thống hoạt động ổn định, Rate Limiting có vai trò quan trọng đối với việc bảo mật của hệ thống, có thể hạn chế được số lượng requests liên tục từ các DoS /DDoS attacks, hay sử dụng Brute-force để dò mật khẩu, Web scraping, Spam, ...

Rate limiting là một cách để hạn chế lượng traffic request, ngoài ra còn giúp giảm tải cho web-server. Hiểu đơn giản thì rate limiting sẽ cho phép gửi số lượng request nhất định trong 1 khoảng thời gian nhất định. Nếu vượt quá sẽ bị block lại.

Ví dụ:

  • Một user chỉ có thể gửi một request mỗi giây.
  • Một user chỉ được phép giao dịch thẻ tín dụng thất bại 3 lần mỗi ngày.
  • Một IP chỉ có thể tạo hai mươi tài khoản mỗi ngày.

Nếu không có cơ chế limit thì với lượng request (có thể đến từ người dùng huặc bot) liên tục như vậy có thể làm chậm, quá tải hay sập cả hệ thống.

Đây là cơ chế API rate limiting của coinmarketcap, dưới đây là một số thông tin: mỗi user sẽ chỉ được cho phép thực hiện tối đa 30 request/phút, 333 request/ngày, 10,000 request/tháng.

API rate limiting

Nếu request vượt quá giới hạn cho phép thì API sẽ trả về một error response như sau:

API trả về response với HTTP Status:429 – Too many requests.

Các lợi ích của rate limiting:

Rate limiting cũng được sử dụng để hạn chế thất thoát doanh thu, giảm chi phí cơ sở hạ tầng, ngăn chặn spam mail, các hành vi phá hoại hệ thống, dưới đây là một số lợi ích mà rate limiting mang lại.

  • Security: giới hạn user thực hiện số lần thử xác thực đăng nhập, ví dụ: số lần user thử password sai.
  • Ngăn chặn hành vi lạm dụng: Nếu không có API limit, user có thể thực hiện lặp lại một request nhiều lần với các thông tin giống nhau.
  • Kiếm soát chi phí và việc sử dụng resource: Client có thể thực hiện một số lượng lớn các requests, đảm bảo các requests có độ ưu tiên thấp không làm ảnh hưởng đến traffic có độ ưu tiên cao hơn.
  • Doanh thu: Mỗi user sẽ được cấp số lượng rate limit nhất định cho mỗi service, nếu muốn thực hiện nhiều hơn sẽ phải trả thêm phí, do đó có thể tạo ra mô hình doanh thu.
  • Loại bỏ lưu lượng tăng đột biến: Đảm bảo service luôn hoạt động để phục vụ cho các users khác.

Các loại rate limits:

Rate limits có nhiều cách thực hiện khác nhau, chúng ta có thể xây dựng ở phía web-server hay web-app huặc cả hai, có thể sử dụng một huặc kết hợp nhiều loại với nhau, điều này còn phụ thuộc vào từng nhu cầu thực tế, Dưới đây là 3 loại rate limiting khác nhau.

User rate limiting:

Đây là cách phổ biến hay dùng nhất, thông thường, rate limiting dựa trên việc theo dõi số lượng các request và khoảng thời gian giữa mỗi request dựa trên địa chỉ IP, Session Cookie huặc API key. Nếu số lượng requests vượt ngưỡng cho phép trong một thời gian nhất định thì nó sẽ bị từ chối, phải đợi cho đến khi khung thời gian reset lại thì mới thực hiện được các requests tiếp theo, error response thường được trả về với "Retry-After" header.

Ví dụ: trong khoảng thời gian 10s chỉ cho phép tối đa 3 requests, nếu vượt quá sẽ bị từ chối.

Rate limiting working

Geographic rate limiting:

Vơi cách này, chúng ta có thể đặt rate-limit cho các khu vực cụ thể và khoảng thời gian cụ thể.

Ví dụ, trong khoảng thời gian nửa đêm 0h - 8h sáng, thường sẽ có ít người sử dụng nên có thể đặt rate-limit thấp xuống để giảm thiểu được các hành động hay tấn công đáng ngờ.

Server rate limiting:

APIs có thể triển khai trên nhiều servers để phục vụ xử lý nhiều requests. Server rate limiting là quá trình thực thi các limits khác nhau cho mỗi server.

Ví dụ: một service được sử dụng với tần suất cao (ví dụ: Black Friday Sales, ...) thì chúng ta sẽ đặt rate-limit cao hơn so với các Web-server khác, để các requests được xử lý nhanh hơn.

Các server ít được truy cập hơn thì có thể giảm request limits để giải phóng network traffic cho server, giúp nhiều API requests được xử lí hơn.

Trong bài viết này chúng ta sẽ tập trung vào: User rate limiting

Một số thuật toán phổ biến

Leaky bucket

Leaky bucket sẽ sử dụng một bucket hay queue, mỗi request gửi đến sẽ được thêm vào cuối danh sách queue, nếu queue đầy thì những requests sau đó sẽ bị loại bỏ, các request trong queue sẽ được xử lí dựa trên quy tắc first come first serve (FCFS).

Cách này dễ dàng triển khai trên một server hay load balancer.

Ví dụ: Network qui định một host có băng thông tối đa 3 Mbps, leaky bucket sẽ được dùng để định hình lưu lượng đầu vào để host không vượt quá giới hạn.

Trong hình dưới, host sẽ gửi dữ liệu với tốc độ 12 Mbps trong 2 giây, với tổng số 24 Mbits dữ liệu, sau 5 giây, tiếp tục gửi dữ liệu với tốc độ 2 Mbps liên tục trong 3 giây, tổng số 6 Mbits dữ liệu.

Tổng cộng, máy chủ đã gửi 30 Mbits dữ liệu trong 10 giây. Leaky bucket định hình lưu lượng bằng cách gửi dữ liệu đi với tốc độ 3 Mbps trong 10 giây.

Nếu không có cơ chế này, thì một host có thể chiếm dụng nhiều băng thông trong network.

Leaky bucket

Ưu điểm

  • Requests sẽ được xử lí trơn tru với khung thời gian cố định.
  • Kích thước của queue không đổi, do đó có hiệu quả về bộ nhớ.

Nhược điểm

  • Một loạt traffic có thể lấp đầy queue với các requests cũ trong một khoảng thời gian và requests mới có thể không được xử lí.
  • Không thể tận dụng hiệu quả resources, leaking rate cố định, vì vậy nó không thể xử lý một lưu lượng lớn traffic vượt quá ngưỡng mặc dù còn dư nhiều resources.

Fixed Window

Thuật toán này timeline sẽ được chia ra thành các khung thời gian cố định - fixed window (1s/1m/1h,...), mỗi khung thời gian sẽ có một counter để đếm số lượng requests trong từng khung thời gian đó. Nếu số lượng requests vượt quá sẽ bị block, counter sẽ được reset sau mỗi khung thời gian.

Ví dụ: Rate limit được cấu hình trong 1 giây sẽ chỉ chấp nhận tối đa 2 request.

\
  • Trong khoảng thời gian từ giây 0.0s -> 1.0s có 2 request là m1 và m2 được gửi đi.
  • Trong khoảng thời gian từ giây 1.0s -> 2.0s có 3 request là m3, m4 và m5.

Như vậy m5 sẽ block lại.

Ưu điểm

  • Dễ thực hiện.
  • Tốn ít bộ nhớ vì chỉ lưu biến đếm trong một khoảng thời gian nhất định.

Nhược điểm

  • Fixed window tồn tại lỗ hổng, ví dụ: tại thời điểm 0.58s, 0.59s chúng ta thực hiện 2 request, sau đó tại 1.0s, 1.1s lại thực hiện thêm 2 request, vậy tổng cộng là 4 request > 2 request / giây, điều này xảy ra tại gần biên của khung thời gian.
  • Phải chờ cho đến khi time frame được reset (ví dụ trong giờ cao điểm như Black Friday sales) có thể làm sập server.

Sliding Window (Rolling Window)

Sliding window dùng để khắc phục lỗ hổng của cơ chế fixed window, trong thuật toán này thì thời gian sẽ được tính từ phần tử thời gian mà request được thực hiện cộng với độ dài của time window.

Ví dụ: Rate limit được cấu hình trong 1 giây sẽ chỉ chấp nhận tối đa 2 request.

Giả sử có hai request m1 và m2 được gửi tại 0.3s và 0.4s, vậy rate limit sẽ bắt đầu được tính từ 0.3s của giây này cho tới 0.3s của giây tiếp theo.

Trong khoảng 0.3s tiếp theo chúng ta thấy có 2 request tiếp theo được gửi đến đó là m3 và m4. Như vậy trong khoảng thời gian 0.6s này đã có 4 request được gửi là m1 ,m2, m3 và m4.

Khi đó hai request m3, m4 sẽ bị block.

Ưu điểm

  • Scale rate limiting linh hoạt với performance tốt.
  • Khắc phục được vấn đề của leaky bucket
  • Khắc phục được hàng loạt requests tại cận khung thời gian của fixed window.

Thiết kế rate-limiting

Chúng ta cần xem xét những điều sau đây khi thiết lập API rate limits.

  • Xác định số lượng requests tối đa mà hệ thống có thể chịu được.
  • Requests có bị giới hạn khi vượt quá limit cho phép?
  • Triển khai rate limit ở web-server hay web-app ?
  • Các requests phát sinh có tính thêm phí (additional fees) ?
  • Các requests mới có nhận được error code trả về không ?

Triển khai API Rate Limiting

Chúng ta sẽ không dùng Mysql để lưu trữ dữ liệu vì tốc độ đọc ghi dữ liệu (từ Disk) sẽ lâu hơn so với memory (RAM), hơn nữa dữ liệu đơn giản nên không cần thiết phải lưu trong Database, với Memcache hay Redis sẽ sử dụng memory để lưu nên tốc độ đọc ghi sẽ rất nhanh.

Performance comparison of in memory and on disk

Đối với Rails chúng ta sẽ sử dụng gem: rack-attack

Thêm vào Gemfile

gem 'rack-attack'

Sau đó bundle install

Tạo một initializer file mới trong config/initializers/rack_attack.rb

Ở đây chúng ta sẽ dùng Memcache, có thể thay bằng Redis nếu muốn.

# config/initializers/rack_attack.rb (for rails apps)

class Rack::Attack
  # Rack::Attack.cache.store = Rack::Attack::StoreProxy::RedisStoreProxy.new(redis_client)
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

  # cho phép 1 IP thực hiện 2 requests mỗi giây
  throttle('req/ip', limit: 2, period: 1) do |req|
    req.ip
  end

  # Gửi error response khi đã đạt ngưỡng
  self.throttled_response = ->(env) {
    retry_after = (env['rack.attack.match_data'] || {})[:period]
    [
      429,
      {'Content-Type' => 'application/json', 'Retry-After' => retry_after.to_s},
      [{error: "Throttle limit reached. Retry after #{retry_after}s"}.to_json]
    ]
  }

end

Đối với rackup:

# In config.ru

require "rack/attack"
use Rack::Attack

Kết quả:


References:

https://nordicapis.com/everything-you-need-to-know-about-api-rate-limiting/
https://www.cloudflare.com/learning/bots/what-is-rate-limiting
https://learnsystemdesign.blogspot.com/p/design-api-rate-limiter.html

RESTful: Phần 3 - API Caching
Previous article

RESTful: Phần 3 - API Caching

Caching là quá trình backup bản sao dữ liệu của database trong cache. Cache là nơi lưu trữ dữ liệu tạm thời với tốc độ truy cập nhanh hơn, caching cải thiện được latency, giảm tải cho server và database


GO TOP

🎉 You've successfully subscribed to itplusX!
OK
]