Giriş
Şu satırı dahil ederiz
import io.github.bucket4j.Bandwidth; import io.github.bucket4j.Bucket; import io.github.bucket4j.ConsumptionProbe; import io.github.bucket4j.Refill;
Maven
Şu satırı dahil ederiz
<dependency> <groupId>com.bucket4j</groupId> <artifactId>bucket4j-core</artifactId> <version>8.1.1</version> </dependency>
Bucket Arayüzü
Açıklaması şöyle
Bucket is the Interface that defines the behavior of a rate-limiter — based on the Token Bucket algorithm.A bucket is created using a builder pattern.Bucket bucket = Bucket.builder().addLimit(...).build();To add a Limit to the bucket, we define a Bandwidth denoted by the following terms.Capacity specifies how many tokens your bucket has.Refill specifies how fast tokens can be refilled after being consumed from a bucket.If we choose the interval refill, the bucket will wait until the whole period is elapsed before regenerating the whole token amount.// generates 10 tokens each minuteRefill.intervally(10, Duration.ofMinutes(1));
Örnek
Elimizde şöyle bir kod olsun
@Configurationpublic class InterceptorConfig extends WebMvcConfigurerAdapter {@AutowiredRateLimitInterceptor rateLimitInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(rateLimitInterceptor);}}
Şöyle yaparız
@Component public class RateLimitInterceptor implements HandlerInterceptor { private final Map<String, Bucket> buckets = new ConcurrentHashMap<>(); private long capacity = 10; private long tokens = 10; Bucket defaultBucket = Bucket.builder() .addLimit(Bandwidth.classic(capacity, Refill.intervally(tokens, Duration.ofMinutes(1)))) .build(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String clientIP = getClientIP(request); logger.info(clientIP); Bucket bucketByClientIP; if (buckets.containsKey(clientIP)) { bucketByClientIP = buckets.get(clientIP); } else { bucketByClientIP = this.defaultBucket; buckets.put(clientIP, bucketByClientIP); } ConsumptionProbe probe = bucketByClientIP .tryConsumeAndReturnRemaining(1); if (probe.isConsumed()) { response.addHeader("X-Rate-Limit-Remaining", Long.toString(probe.getRemainingTokens())); return true; } response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); // 429 response.addHeader("X-Rate-Limit-Retry-After-Milliseconds", Long.toString(TimeUnit.NANOSECONDS.toMillis(probe.getNanosToWaitForRefill()))); return false; } }
Açıklaması şöyle
The magic of this library is in the isConsumed() method. After asking the bucket to consume a token from the basket, we test whether the token was consumed. If true, the limit was not exceeded, and the API allows the client to consume the endpoint. Otherwise, the limit was exceeded, and we rejected the request, returning an HTTP error code of 429 to the client.
IP bulma kodu şöyledir
private String getClientIP(HttpServletRequest request) { String ip = request.getHeader("X-FORWARDED-FOR"); if (ip == null || ip.isEmpty()) { ip = request.getRemoteAddr(); } return ip; }
Hiç yorum yok:
Yorum Gönder