• 网关之多维度限流


    github https://github.com/marcosbarbero/spring-cloud-zuul-ratelimit

    spring-cloud-zuul-ratelimit 说明

    spring-cloud-zuul-ratelimit是和zuul整合提供分布式限流策略的扩展

    • 对请求的目标URL进行限流(例如:某个URL每分钟只允许调用多少次)
    • 对客户端的访问IP进行限流(例如:某个IP每分钟只允许请求多少次)
    • 对某些特定用户或者用户组进行限流(例如:非VIP用户限制每分钟只允许调用100次某个API等)
    • 多维度混合的限流。此时,就需要实现一些限流规则的编排机制。与、或、非等关系。

    支持的限流粒度

    • 服务粒度 (默认配置,当前服务模块的限流控制)
    • 用户粒度
      用户限流的实现:如果你的项目整合 Shiro 或者 Spring Security 安全框架,那么会自动维护request域UserPrincipal,如果是自己的框架,请登录成功后维护request域UserPrincipal,才能使用用户粒度的限流。未登录默认是:anonymous
    • ORIGIN粒度 (用户请求的origin作为粒度控制)
      某个IP的客户端被限流并不影响其他客户端,即API网关对每个客户端限流是相互独立的
    • URL 接口粒度 (请求接口的地址作为粒度控制)
    • 以上粒度自由组合,又可以支持多种情况。
    • 如果还不够,自定义RateLimitKeyGenerator实现

    支持数据存储

    • InMemoryRateLimiter - 使用 ConcurrentHashMap作为数据存储
    • ConsulRateLimiter - 使用 Consul 作为数据存储
    • RedisRateLimiter - 使用 Redis 作为数据存储
    • JpaRateLimiter - 使用 数据库 作为数据存储
    • Bucket4j JCache 等其它缓存存储

    pom 依赖

            <dependency>
                <groupId>com.marcosbarbero.cloud</groupId>
                <artifactId>spring-cloud-zuul-ratelimit</artifactId>
                <version>1.7.1.RELEASE</version>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    

    限流配置

    • limit 单位时间内允许访问的次数
    • quota 单位时间内允许访问的总时间(单位时间窗口期内,所有的请求的总时间不能超过这个时间限制)
    • refresh-interval 单位时间设置
    • type 限流类型
      1. url类型的限流就是通过请求路径区分
      2. origin是通过客户端IP地址区分
      3. user是通过登录用户名进行区分,也包括匿名用户
    • default-policy 可选 - 针对所有的路由配置的策略,除非特别配置了policy-list
    • policies 对特定的服务id进行限流
      • 缺点
        • 可以配置多个url,但是这些url都使用一个限流配置,没有办法指定每个url的限流配置
    • policy-list 对特定的服务id进行限流
      • 优点
        • 可以为某个服务id的每个url 指定不同的限流配置

    policies 配置多个url共用一个限流次数

    zuul.routes.hello-feign.path=/hello-feign/**
    zuul.routes.hello-feign.serviceId=feign-service-1
    
    #*********************************************************
    #  特定的路由
    #
    # 测试客户端 30秒内允许10个访问,并且要求总请求时间小于20秒
    #
    #*********************************************************
    zuul.ratelimit.policies.hello-feign.limit=10
    zuul.ratelimit.policies.hello-feign.quota=20
    zuul.ratelimit.policies.hello-feign.refreshInterval=30
    
    zuul.ratelimit.policies.hello-feign.type[0].type=url
    zuul.ratelimit.policies.hello-feign.type[0].matcher=/custom/zuul/test
    
    zuul.ratelimit.policies.hello-feign.type[1].type=url
    zuul.ratelimit.policies.hello-feign.type[1].matcher=/custom/zuul/timeout
    
    

    policy-list 配置每个url的限流次数

    zuul.routes.hello-feign.path=/hello-feign/**
    zuul.routes.hello-feign.serviceId=feign-service-1
    
    zuul.ratelimit.policy-list.hello-feign.[0].limit=10
    zuul.ratelimit.policy-list.hello-feign.[0].quota=4
    zuul.ratelimit.policy-list.hello-feign.[0].refreshInterval=10
    zuul.ratelimit.policy-list.hello-feign.[0].type[0].type=url
    zuul.ratelimit.policy-list.hello-feign.[0].type[0].matcher=/custom/zuul/test
    
    zuul.ratelimit.policy-list.hello-feign.[1].limit=2
    zuul.ratelimit.policy-list.hello-feign.[1].quota=4
    zuul.ratelimit.policy-list.hello-feign.[1].refreshInterval=10
    zuul.ratelimit.policy-list.hello-feign.[1].type[0].type=url
    zuul.ratelimit.policy-list.hello-feign.[1].type[0].matcher=/request-body
    
    

    扩展 策略生成的key,因为默认的策略key 在循环policy-list 的配置时会将当前的url对应的策略 policy 覆盖掉。

    @Configuration
    public class CustomPolicy extends DefaultRateLimitKeyGenerator {
    
        private final RateLimitProperties properties;
        private final RateLimitUtils rateLimitUtils;
    
    
        public CustomPolicy(RateLimitProperties properties, RateLimitUtils rateLimitUtils) {
            super(properties, rateLimitUtils);
            this.properties = properties;
            this.rateLimitUtils = rateLimitUtils;
        }
    
        @Override
        public String key(HttpServletRequest request, Route route, RateLimitProperties.Policy policy) {
            // 获取当前 policy 的索引
            int indexOf = properties.getPolicies(route.getId()).indexOf(policy);
    
            final List<RateLimitProperties.Policy.Type> types = policy.getType().stream().map(RateLimitProperties.Policy.MatchType::getType).collect(Collectors.toList());
            final StringJoiner joiner = new StringJoiner(":");
            joiner.add(properties.getKeyPrefix());
            if (route != null) {
                joiner.add(route.getId());
            }
            if (!types.isEmpty()) {
                if (types.contains(RateLimitProperties.Policy.Type.URL) && route != null) {
                    joiner.add(route.getPath());
                }
                if (types.contains(RateLimitProperties.Policy.Type.ORIGIN)) {
                    joiner.add(rateLimitUtils.getRemoteAddress(request));
                }
                if (types.contains(RateLimitProperties.Policy.Type.USER)) {
                    joiner.add(rateLimitUtils.getUser(request));
                }
            }
            
            // 添加索引
            joiner.add(String.valueOf(indexOf));
    
            return joiner.toString();
    
        }
    }
    
    

    其它限流配置项

    # redis
    spring.redis.port=6379
    spring.redis.host=127.0.0.1
    spring.redis.timeout=2000
    
    # 开启限流
    zuul.ratelimit.enabled=true
    # 对应用来标识请求的key的前缀
    zuul.ratelimit.key-prefix=hello-feign
    zuul.ratelimit.repository=redis
    # 代理之后
    zuul.ratelimit.behind-proxy=true
    
    
  • 相关阅读:
    高级语言是面向用户的
    汇编语言指令是机器指令的符号化
    程序设计语言具有心理工程及技术
    语言的种类成分
    程序设计方法和过程
    程序设计的基本概念
    结构化程序设计与非结构化程序设计之分
    常见语言计算机语言
    语言的基础是一组记号和一组规则
    面向对象的基本概念
  • 原文地址:https://www.cnblogs.com/zhangjianbin/p/9110451.html
Copyright © 2020-2023  润新知