• spring cloud 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

     原文:https://blog.csdn.net/m0_37834471/article/details/82621353


    redis限流原文:https://blog.csdn.net/ifrozen/article/details/80016566 

  • 相关阅读:
    pgsql 时间转时间戳
    java SHA-1加密
    java 输出json文件
    按照指定字符串截取文本
    java 科学计数法转换
    【原创】几个常用机场的对比
    【原创】Google Cloud服务器路由分析
    批量转换文件Unicode到中文
    博客搬家
    关于zookeeper
  • 原文地址:https://www.cnblogs.com/tflike/p/10044877.html
Copyright © 2020-2023  润新知