The background,

The Soul gateway provides three plug-ins for traffic limiting

  • RateLimiter relies on the token bucket made by Redis
  • Hystrix is based on RxJava and has not been updated for several years. It is probably mature and stable, and there is no need to update
  • Sentinel Ali open source
  • After the suspension of The Resilience4J Hystrix, Netflix recommended to move to The Resilience4J framework, which is a lightweight, easy-to-use, and assemblable high availability framework that supports multiple high availability mechanisms such as circuit breaker, high frequency control, isolation, flow limiting, time limiting, and retry.

I got a comparison from the Internet

Sensory learning Soul gateway, as the gateway to distributed services, to learn all around the technology. Microprofile. IO /, it turns out that the world of distributed services is not just Spring or Service Mech. MicroProfile has several microservice-like specifications endorsed by IBM, Red Hat, and an open source community implementation project supported by Red Hat. Here is an article introduces my.oschina.net/u/4567873/b…

There is also a document download.eclipse.org/microprofil…

Anyway, back to the point.

Two, start learning

Sleepy, I will not demonstrate, directly look at the plug-in code ~ ~

1, RateLimiter

    protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
        final String handle = rule.getHandle();
        final RateLimiterHandle limiterHandle = GsonUtils.getInstance().fromJson(handle, RateLimiterHandle.class);
        return redisRateLimiter.isAllowed(rule.getId(), limiterHandle.getReplenishRate(), limiterHandle.getBurstCapacity())
                .flatMap(response -> {
                    if(! response.isAllowed()) { exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); Object error = SoulResultWrap.error(SoulResultEnum.TOO_MANY_REQUESTS.getCode(), SoulResultEnum.TOO_MANY_REQUESTS.getMsg(),null);
                        return WebFluxResultUtils.result(exchange, error);
                    }
                    return chain.execute(exchange);
                });
    }
Copy the code

RedisRateLimiter#isAllowed indicates the method of limiting traffic

    public Mono<RateLimiterResponse> isAllowed(final String id, final double replenishRate, final double burstCapacity) {
        if (!this.initialized.get()) {
            throw new IllegalStateException("RedisRateLimiter is not initialized");
        }
        List<String> keys = getKeys(id);
        List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", Instant.now().getEpochSecond() + ""."1");
        Flux<List<Long>> resultFlux = Singleton.INST.get(ReactiveRedisTemplate.class).execute(this.script, keys, scriptArgs);
        return resultFlux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L)))
                .reduce(new ArrayList<Long>(), (longs, l) -> {
                    longs.addAll(l);
                    return longs;
                }).map(results -> {
                    boolean allowed = results.get(0) = =1L;
                    Long tokensLeft = results.get(1);
                    RateLimiterResponse rateLimiterResponse = new RateLimiterResponse(allowed, tokensLeft);
                    log.info("RateLimiter response:{}", rateLimiterResponse.toString());
                    return rateLimiterResponse;
                }).doOnError(throwable -> log.error("Error determining if user allowed from redis:{}", throwable.getMessage()));
    }
Copy the code

You can see that the Redis operation is in Reactive mode, the specific Lua script

    private RedisScript<List<Long>> redisScript() {
        DefaultRedisScript redisScript = new DefaultRedisScript<>();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/META-INF/scripts/request_rate_limiter.lua")));
        redisScript.setResultType(List.class);
        return redisScript;
    }
Copy the code

In/meta-INF /scripts/request_rate_limiter. Lua, I can’t read it anyway.

2, Hystrix

Hystrix has not been updated for 4 years, RxJava does not have ProjectReactor fire, and Netfix officials have asked you to step up Resilience4J ~ _ ~

3, Sentinel

I can’t get away with that. I’ll give up.

4, Resilience4J

Resilience4j is a lightweight fault-tolerant framework designed for Java8 and functional programming, inspired by Netflix Hystrix. The framework simply uses Varr’s library, without introducing any other external dependencies. In contrast, Netflix Hystrix has a compile dependency on Archaius, which requires more external dependencies, such as Guava and Apache Commons Configuration.

Finally, the recommend an article to introduce Sentinel my.oschina.net/xiaominmin/…

Anyway, life is short, so with all the current limiting tools, choose Sentinel, it’s really energetic. I’m looking at Redis current limiting.