https://github.com/google/guava
guava est fourni par google en tant que OSS et fournit divers processus de base requis par Java en tant que bibliothèque. Il contient une classe appelée RateLimiter pour le traitement de limitation de débit, alors utilisons-la facilement.
Sample --PERMITS_PER_SECONDS: nombre de processus pouvant être traités en même temps --PERMITS_CONSUMED: Nombre de processus consommés dans un processus (modifiez cette valeur si vous souhaitez modifier le poids d'un processus) --RateLimiter # tryAcquire: Une méthode qui teste si le PERMITS_CONSUMED passé peut être consommé. Le deuxième argument est la valeur du délai d'expiration. Renvoie true si elle peut être obtenue avant l'expiration du délai, false dans le cas contraire.
Si vous essayez de réaliser une limitation de débit avec le contrôleur de Spring Boot en utilisant le mécanisme, ce sera comme suit.
@Slf4j
@Controller
public class TestController {
private static final Double PERMITS_PER_SECONDS = 1d;
private static final int PERMITS_CONSUMED = 1;
private AtomicInteger index = new AtomicInteger(0);
private RateLimiter rateLimiter = RateLimiter.create(PERMITS_PER_SECONDS);
@GetMapping("/hello")
@ResponseBody
public HashMap<String, String> sayHello() {
final int id = index.incrementAndGet();
final boolean acquired = rateLimiter.tryAcquire(PERMITS_CONSUMED, Duration.ofMillis(100L));
if (!acquired) {
throw new UncheckedIOException(new IOException("Rate Limit."));
}
log.debug("Serving request id " + id);
return new HashMap<>() {{
put("message", "Hello");
put("id", String.valueOf(id));
put("acquired", String.valueOf(acquired));
}};
}
}
En utilisant RateLimter pour contrôler exclusivement le nombre de processus simultanés de la manière ci-dessus, un traitement de limitation de débit simple peut être mis en œuvre.
Running
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Mon, 20 Apr 2020 10:38:20 GMT
<
{ [60 bytes data]
100 49 0 49 0 0 24500 0 --:--:-- --:--:-- --:--:-- 24500
* Connection #0 to host localhost left intact
{"id":"3092","message":"Hello","acquired":"true"}
< HTTP/1.1 500
< Content-Type: application/json
< Transfer-Encoding: chunkedj
< Date: Mon, 20 Apr 2020 10:38:43 GMT
< Connection: close
< [
{ [5072 bytes data]
*100 5064 0 5064 0 0 2472k 0 --:--:-- --:--:-- --:--:-- 2472k
* Closing connection 0
{"timestamp":"2020-04-20T10:38:43.015+0000","status":500,"error":"Internal Server Error","message":"java.io.IOException: Rate Limit.","t
race":"java.io.UncheckedIOException: java.io.IOException: Rate Limit. (snip.)
Appendix Vous pouvez écrire un traitement Naive Rete-Limiting comme ci-dessus en utilisant le RateLimiter de goyave.
Cependant, la limitation de débit a de nombreux aspects à prendre en compte lors de la mise en œuvre et de l'exploitation, de sorte qu'il n'est peut-être pas très réaliste de la mettre en œuvre à partir de zéro.
Armeria est un framework Web qui utilise RateLimter pour effectuer la limitation de débit sur OSS dans le monde.
https://github.com/line/armeria
https://github.com/line/armeria/blob/f03b400cff136a710dbdbeb75e0e4f741387d296/core/src/main/java/com/linecorp/armeria/server/throttling/RateLimitingThrottlingStrategy.java
Armeria vous permet de définir le traitement de Throttling (Rate-Limiting) avec Decorator, ce qui semble facile à introduire. Je pense qu'une façon est de développer une application Web en utilisant ces OSS.
https://image.slidesharecdn.com/2018-180227110721/95/building-asynchronous-microservices-with-armeria-24-638.jpg?cb=1519731604
Armeria prend également en charge la limitation basée sur bucket4j (Token Bucket).
https://github.com/line/armeria/blob/e8eecafb35bb7eb50f6cdd614b0b5d1faca8a308/bucket4j/src/main/java/com/linecorp/armeria/server/throttling/bucket4j/TokenBucketThrottlingStrategy.java