springCloud(一)-----网关之限流

前言

spring cloud gateway作为一种简单有效的统一的API路由管理方式,为我们限流措施提供了一个有效的入口。

一. 限流算法

本文从常用的令牌桶限流算法说起,看如何让在网关中做请求限制。羊会在后续文章中和大家探讨一下一些限流算法,并会在后续文章中讨论下分布式环境中如何在网关限流,请大家持续关注我的文章。

二. 创建工程

2.1 创建一个spring cloud gateway工程
(相信大家早已不陌生,此处省略)
2.2 引入Bucket4j依赖

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

2.3 创建网关过滤器

@Component
@Slf4j
@RefreshScope
public class IpRegisterFilter implements GlobalFilter, Ordered {  

    public static final String WARNING_MSG = "访问太频繁了!";

    public static final Map<String, Bucket> LOCAL_CACHE = new ConcurrentHashMap<>();

    // 令牌桶初始容量3    
    private Integer CAPACITY = 3;

    // 补充桶的时间间隔,即60秒补充一次    
    private long PERIOD = 60;

    // 每次补充token的个数
    public static final long REPLENISH = 1;


    @Override
    public Mono<Void> filter(ServerWebExchange serverWebExchange, GatewayFilterChain gatewayFilterChain) {
        ServerHttpRequest request = serverWebExchange.getRequest();
        ServerHttpResponse response = serverWebExchange.getResponse();

        if (request.getURI().getPath().contains( "/你的path" )) {
            String ip = request.getRemoteAddress().getHostString();
            log.info( "访问IP为:{}", ip );

            Bucket bucket = LOCAL_CACHE.computeIfAbsent( ip, k -> createNewBucket( ip ) );

            log.info( "IP:{} ,令牌通可用的Token数量:{} ", ip, bucket.getAvailableTokens() );

            if (bucket.tryConsume( 1 )) {
                // 直接放行
                return gatewayFilterChain.filter( serverWebExchange );
            } else {
                //指定编码
                response.getHeaders().add( "Content-Type", "text/plain;charset=UTF-8" );
                response.setStatusCode( HttpStatus.FORBIDDEN ); // 状态码
                byte[] data = WARNING_MSG.getBytes( StandardCharsets.UTF_8 );
                DataBuffer wrap = response.bufferFactory().wrap( data );
                return response.writeWith( Mono.just( wrap ) );
            }
        }
        return gatewayFilterChain.filter( serverWebExchange );           
    }

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

    private Bucket createNewBucket(String ip) {
        Duration replenishDuration = Duration.ofSeconds( PERIOD );
        Refill refill = Refill.of( REPLENISH, replenishDuration );
        Bandwidth limit = Bandwidth.classic( CAPACITY, refill );
        return Bucket4j.builder().addLimit( limit ).build();
    }
}

至此,关键部分已完成。相信大家看到限流桶放在了map里,无法在多实例里应用。不要担心,请关注我后续文章,我会和大家探讨下如何在分布式环境中应用限流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

相关阅读更多精彩内容

友情链接更多精彩内容