Đang mở...

Sử dụng Bucket4j để thực hiện rate limiting trong Java

1. Giới thiệu Blog này, Chúng ta sẽ tìm hiểu về rate limiting và lợi ích của việc sử dụng Bucket4j cho rate limiting trong ứng dụng Java. Rate Limiting...
Danh mục Blog
26/06/2023
Sử dụng Bucket4j để thực hiện rate limiting trong Java

1. Giới thiệu

Blog này, Chúng ta sẽ tìm hiểu về rate limiting và lợi ích của việc sử dụng Bucket4j cho rate limiting trong ứng dụng Java.

Rate Limiting

Đầu tiên, ta sẽ giới thiệu về rate limiting là gì. Rate limiting là một kỹ thuật được sử dụng để kiểm soát số lượng hoặc tần suất các hoạt động mà một hệ thống hoặc API có thể xử lý từ một nguồn yêu cầu. Rate limiting giúp đảm bảo rằng nguồn tài nguyên của hệ thống không bị quá tải và giúp bảo vệ ứng dụng khỏi các cuộc tấn công DDoS và các hành vi lạm dụng khác.

Bucket4j

Tiếp theo, chúng ta sẽ tìm hiểu về Bucket4j. Bucket4j là một thư viện Java hỗ trợ thực hiện rate limiting dựa trên các hệ thống Bucket-based algorithms như Token Bucket và Leaky Bucket. Bucket4j cung cấp các công cụ mạnh mẽ để cấu hình và quản lý các rate limiter và cung cấp tính năng linh hoạt như giới hạn số lượng yêu cầu hoặc lưu lượng dữ liệu trong một khoảng thời gian nhất định.

Vậy việc sử dụng Bucket4j trong ứng dụng Java có lợi ích như thế nào? Bucket4j giúp đơn giản hóa quá trình thực hiện rate limiting bằng cách cung cấp API dễ sử dụng và các tính năng linh hoạt để cấu hình và tùy chỉnh các rate limiter. Nó cũng hỗ trợ tính toán rate limiting trên cấu trúc dữ liệu phân tán như Redis, cho phép ứng dụng mở rộng và linh hoạt trong việc quản lý rate limiting trên môi trường phân tán.

Trong phần tiếp theo của hướng dẫn, chúng ta sẽ tiến hành cài đặt Bucket4j và khám phá cách sử dụng thư viện này để thực hiện rate limiting trong ứng dụng Java của chúng ta.

2. Cài đặt

Để sử dụng rate limiting trong project, phải thêm phần phụ thuộc Bucket4j Spring Boot Starter vào dự án của mình. Ngoài ra, bạn phải chọn nhà cung cấp bộ nhớ đệm. Ví dụ tiếp theo sử dụng JSR 107 Ehcache sẽ được cấu hình tự động với Spring Boot Starter Cache.

<dependency>
    <groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
    <artifactId>bucket4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

3. Cấu hình Rate Limiting

Cấu hình có thể được thực hiện trong application.properties/application.yml.

Ví dụ đơn giản đầu tiên chúng ta sẽ cấu hình như sau:

bucket4j:
  enabled: true
  filters:
  - cache-name: buckets
    url: .*
    rate-limits:
    - bandwidths:
      - capacity: 5
        time: 10
        unit: seconds

Trong đoạn cấu hình trên, chúng ta đang cấu hình rate limit bằng Bucket4j:

  • enabled: true: Đây là thuộc tính để bật hoặc tắt tính năng rate limit. Khi đặt thành true, rate limit sẽ được kích hoạt.
  • filters: Đây là một danh sách các bộ lọc mà rate limit sẽ được áp dụng. Trong trường hợp này, chúng ta chỉ có một bộ lọc.
  • cache-name: buckets: Đây là tên của cache mà Bucket4j sử dụng để lưu trữ thông tin về rate limit. Cache này sẽ lưu trữ thông tin về số lượng token còn lại và thời gian hết hạn của từng IP hoặc URL.
  • url: .*: Đây là biểu thức chính quy để áp dụng rate limit cho tất cả các URL. Trong trường hợp này, rate limit sẽ được áp dụng cho tất cả các yêu cầu.
  • rate-limits: Đây là danh sách các rate limit mà chúng ta muốn cấu hình.
  • bandwidths: Đây là danh sách các bandwidth (băng thông) được cấu hình cho rate limit.
  • capacity: 5: Đây là dung lượng tối đa của bucket (hòm đựng token). Nghĩa là bucket này có thể chứa tối đa 5 token.
  • time: 10: Đây là khoảng thời gian mà bucket sẽ được cấp lại đủ token. Trong trường hợp này, bucket sẽ được cấp lại đủ 5 token trong khoảng thời gian là 10 giây.
  • unit: seconds: Đây là đơn vị thời gian được sử dụng cho rate limit. Trong trường hợp này, đơn vị là giây.

Tổng quan, đoạn cấu hình trên định nghĩa một rate limit cho tất cả các URL, giới hạn số lượng yêu cầu tối đa là 5 trong khoảng thời gian 10 giây.

Đối với Ehcache 3, bạn cũng cần một tệp ehcache.xml có thể được đặt trong đường dẫn lớp. Bộ chứa tên bộ đệm được định cấu hình phải được xác định trong tệp cấu hình.

spring:
  cache:
    jcache:
      config: classpath:ehcache.xml
<config xmlns="...">
      <cache alias="buckets">
            <expiry>
                  <ttl unit="seconds">3600</ttl>
            </expiry>
            <heap unit="entries">1000000</heap>
      </cache>

</config>

Ngoài ra, Bucket4J cung cấp cho chúng ta khả năng rate limiting với từng URL, user, ip,…

Tiếp sau đây chúng ta sẽ cấu hình rate limiting theo địa chỉ IP.

bucket4j:
  enabled: true
  filters:
    - cache-name: buckets
      filter-method: servlet
      url: .*
      metrics:
        tags:
          - key: IP
            expression: getRemoteAddr()
            types: REJECTED_COUNTER
      rate-limits:
        - cache-key: getRemoteAddr()
          bandwidths:
            - capacity: 5
              time: 1
              unit: minutes

Cũng giống như trên thế nhưng với việc config rate limiting theo địa chỉ ip lần này chúng ta sẽ có thêm một vài “từ khóa” mới:

  • “key: IP”: Đây là giá trị cho thẻ key, được sử dụng để xác định địa chỉ IP của yêu cầu.
  • “types: REJECTED_COUNTER”: Đây là loại thông số thống kê muốn thu thập. Trong trường hợp này, chúng ta muốn thu thập số lượng yêu cầu bị từ chối.
  • “cache-key: getRemoteAddr()”: Đây là khóa (key) sử dụng trong cache để lưu trữ thông tin rate limit. Trong trường hợp này, chúng ta sử dụng địa chỉ IP làm khóa. Ngoài ra, chúng ta có thể thay getRemoteAddr() bằng @securityService.username() để config rate limiting theo user.

4. Kết quả

Sau khi config rate limiting cho project, khi request vượt quá số lượng cho phép trong một đơn vị thời gian, các request đó lập tức được phía server trả về status code 429.

Cấu hình rate limiting theo địa chỉ ip, những request có type là REJECTED_COUNTER là những request bị chặn do quá số lượng.

5. Kết luận

Đầu tiên, chúng ta đã giới thiệu về khái niệm rate limit và tại sao nó quan trọng trong việc bảo vệ ứng dụng khỏi quá tải và tấn công từ chối dịch vụ (DDoS). Chúng ta đã tìm hiểu về các loại rate limit phổ biến, bao gồm token bucket và leaky bucket, và tập trung vào cách sử dụng Bucket4j để triển khai token bucket rate limit trong ứng dụng Java của chúng ta.

Tiếp theo, chúng ta đã khám phá cách tích hợp Bucket4j vào dự án Spring Boot. Chúng ta đã thêm dependency bucket4j-spring-boot-starter và các dependency cho caching provider, như Ehcache. Chúng ta đã cấu hình rate limit bằng cách sử dụng tệp cấu hình application.yml, chỉ định bandwidth (dung lượng) của rate limit theo nhu cầu của ứng dụng.

Chúng ta đã tìm hiểu về cách Bucket4j hoạt động, bao gồm quản lý token bucket, cấp lại token theo tốc độ được xác định và kiểm tra xem một yêu cầu cụ thể có được chấp nhận hay từ chối dựa trên rate limit.

Cuối cùng, chúng ta đã tìm hiểu về các tính năng mở rộng của Bucket4j, bao gồm thu thập thông tin thống kê và cấu hình rate limit cho từng địa chỉ IP hoặc người dùng.

Từ bài viết này, bạn đã có kiến thức cơ bản để triển khai rate limit trong ứng dụng Java của mình bằng cách sử dụng Bucket4j. Bằng cách áp dụng rate limit, bạn có thể kiểm soát lưu lượng yêu cầu, tăng tính ổn định và bảo mật của ứng dụng.

Hãy áp dụng những gì bạn đã học được từ bài viết này vào dự án của mình và tận dụng sức mạnh của Bucket4j để đảm bảo hiệu suất và bảo mật cho ứng dụng của bạn.

SOURCE CODE THAM KHẢO: source_code

Tài liệu tham khảo

  1. https://bucket4j.com/
  2. https://github.com/khanhtran192/ehcache#spring-boot-starter-bucket4j-08

Trần Duy Khánh

Chia sẻ bài viết này

Leave a Reply Câu trả lời

Địa chỉ email của bạn sẽ không được công bố.

Các nội dung liên quan

Xem các nội dung liên quan

13/06/2023
Tìm hiểu về Gitlab CI/CD
I. Tổng quan GitLab CI là một phần của GitLab, là một hệ thống quản lý mã nguồn Git dựa trên web và một công cụ liên kết liền mạch để...
06/06/2023
Tìm hiểu về Lists và Keys trong React
Đã bao giờ bạn đặt câu hỏi rằng tại sao lại cần key khi map 1 mảng? Tôi chắc chắn bạn đã gặp cảnh báo này: Chỉ cần thêm thuộc...
19/05/2023
Hướng dẫn dùng Jquery Ajax submit form và gọi REST API
AJAX đại diện cho Asynchronous JavaScript And XML bằng cách sử dụng đối tượng XMLHttpRequest để tương tác với máy chủ (server).
12/05/2023
Spring Email
Bài viết giúp bạn tạo ra ứng dụng gửi tin nhắn email với spring email Tìm nhiên liệu cho phần application.properties Vào phần google accout của bạn và làm theo...