(三十)java版spring cloud+spring boot+redis多租户社交电子商务平台- gateway限流

电子商务平台源码请加企鹅求求:一零三八七七四六二六。限流一般有两个实现方式,令牌桶和漏桶。金牌桶是初始化令牌(容器)的个数,通过拿走里边的令牌就能通过, 没有令牌不能报错,可以设置...

电子商务平台源码请加企鹅求求:一零三八七七四六二六。限流一般有两个实现方式,令牌桶和漏桶。


金牌桶是初始化令牌(容器)的个数,通过拿走里边的令牌就能通过, 没有令牌不能报错,可以设置向容器中增加令牌的速度和最大个数


漏桶是向里边放入请求,当请求数量达到最大值后,丢弃,漏桶中的数据以一定速度流出,没有则不流出


金牌桶实现方式如下:


pom

<dependency>
    <groupId>com.github.vladimir-bukhtoyarov</groupId>
    <artifactId>bucket4j-core</artifactId>
    <version>4.0.0</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

创建下边类并且继承下边类 

public class LimitFilter implements GatewayFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(LimitFilter.class);

    int capacity;
    int refillTokens;
    Duration refillDuration;

    public LimitFilter(int capacity, int refillTokens, Duration refillDuration) {
        this.capacity = capacity;
        this.refillTokens = refillTokens;
        this.refillDuration = refillDuration;
    }

    private static final Map<String,Bucket> CACHE = new ConcurrentHashMap<>();
    private Bucket createNewBucket() {
        Refill refill = Refill.of(refillTokens,refillDuration);
        Bandwidth limit = Bandwidth.classic(capacity,refill);
        return Bucket4j.builder().addLimit(limit).build();
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        Bucket bucket = CACHE.computeIfAbsent(ip,k -> createNewBucket());
        logger.info("IP: " + ip + ",TokenBucket Available Tokens: " + bucket.getAvailableTokens());
        if (bucket.tryConsume(1)) {
            return chain.filter(exchange);
        } else {
            exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
            return exchange.getResponse().setComplete();
        }

    }

    @Override
    public int getOrder() {
        return 0;
    }
}

配置路由

  @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
// @formatter:off
        return builder.routes()
                .route(r -> r.path("/consulserver/**")
                        .filters(f -> f.stripPrefix(1)
                                .filter(new LimitFilter(10,1,Duration.ofSeconds(1))))
                        .uri("lb://consulserver")
                        .order(0)
                        .id("throttle_customer_service")
                ).build();
// @formatter:on
    }


  • 发表于 2019-05-31 16:10
  • 阅读 ( 203 )
  • 分类:Java基础

条评论

请先 登录 后评论
不写代码的码农
IT达人

212 篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除