Spring Boot でのレート制限を実装する方法は何ですか?

Spring Boot では、次のような方法でレートリミッティングを実装できます。

  1. アノテーションベースの制限:カスタムアノテーションを使用することで、インターフェイスメソッドにアノテーションを追加し、アクセス回数を制限できます。メソッドにアノテーションを追加することで、許可される最大アクセス数、時間ウィンドウなどのパラメータを設定できます。
@RateLimit(max = 100, duration = 60)
@GetMapping("/api/someEndpoint")
public String someEndpoint() {
    // 方法逻辑
}
  1. インターセプターによる制限:インターセプターを作成し、そこでインターフェイスの制限制御を行います。インターセプターは、要求がコントローラーに出入りする前に、または後で、対応するロジックを実行できます。
@Component
public class RateLimitInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断访问次数是否超过限制
        if (isRateLimited(request)) {
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Rate limit exceeded");
            return false;
        }
        return true;
    }

    private boolean isRateLimited(HttpServletRequest request) {
        // 判断访问次数是否超过限制的逻辑
    }
}

Spring Bootでインターセプターを登録する:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private RateLimitInterceptor rateLimitInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimitInterceptor);
    }
}
  1. キャッシュベースの制限:それぞれの API へのアクセス回数と時間をキャッシュに記録しておきます。リクエストが来るたびに、キャッシュ内のカウンターを確認し、制限を超えていたらリクエストを拒否します。コード例:
@Component
public class RateLimitService {

    private final Cache<String, AtomicInteger> cache;

    public RateLimitService() {
        cache = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(1, TimeUnit.MINUTES)
                .build();
    }

    public boolean isRateLimited(String key, int max, long duration) {
        AtomicInteger counter = cache.get(key, () -> new AtomicInteger(0));
        int count = counter.incrementAndGet();
        if (count > max) {
            return true;
        }
        return false;
    }
}

RateLimitServiceを用いてコントローラでレート制限を行う

@RestController
public class SomeController {

    @Autowired
    private RateLimitService rateLimitService;

    @GetMapping("/api/someEndpoint")
    public String someEndpoint(HttpServletRequest request) {
        String key = request.getRemoteAddr();
        if (rateLimitService.isRateLimited(key, 100, 60)) {
            return "Rate limit exceeded";
        }
        // 方法逻辑
    }
}

Spring Bootでレートリミットを実装するための方法としては、要件に基づいて実装に適した方法を選択できます。

bannerAds