上图是一个大坝泄洪示意图。那么,对于软件系统来说,如何使用最方便的可编程方式来增加业务限流能力呢?接下来结合一个正规的springCloud项目进行实践,希望他山之石可以用于玉石。后台干脆用jmeter,按20并发,访问列表查询接口/worksheet/findInfo,对应的服务就崩溃了。[apprun,common]一类架构复杂性是:保护API和服务端点免受拒绝服务、级联故障或资源超额订阅等攻击。限流是一种控制API或服务消费速度的技术。在分布式系统中,没有比集中配置和管理API消费速度更好的选择了。只有在限定的速度内访问这些请求,才能保证API的正常运行,才会产生更频繁的Http请求错误。交互模型图:SpringCloudGateway是一个简单轻量级的组件,也是管理和限制API消费速度的有效方式。springCloudGateway的限流模型:目标当前企业有600名员工,预计翻倍,即1200人使用,高频接口限时20秒,即20人使用同一接口同时操作数据。需要增加限流和断路器的点:组件增加限流业务说明openresty限流,断路器【统一】保证流量后nginx的处理阈值,参考数据:5W/Sgateway限流,断路器【统一】到保证每个API的访问速度在20/S峰值40;Apprun高频接口限流,每个接口统一分类自定义熔断逻辑限流可复用封装组件,熔断器采用最简单的hystix;devops高频接口限流,每个接口统一分类定制熔断逻辑限流,可复用封装组件。最简单的hystix用于fuse;最简单的hystix;job高频接口限流,每个接口归类到统一的自定义熔断逻辑,feign自定义熔断逻辑限流可以复用封装好的组件,使用最简单的hystix进行熔断;实现路径网关作为整体限流,接口由业务控制增加限流。gatewaygateway有自己的过滤器RequestRateLimiterGatewayFilter工厂使用RateLimiter实现来判断是否允许处理当前的并发请求。如果无法处理,则返回默认状态码429——请求过多;这个过滤器使用了可选的KeyResolver参数和针对速率限制的特殊参数,下面会介绍。keyResolver是一个实现KeyResolver接口的实体,配置为使用SpEL表达式指向bean的名称。#{@myKeyResolver}是一个指向名为myKeyResolver的bean的SPEL表达式。KeyResolver接口如下图;publicinterfaceKeyResolver{Monoresolve(ServerWebExchangeexchange);}keyResolver接口是一个插件化的策略驱动的请求限制,未来的里程碑版本会通过一些KeyResolver来实现。默认实现KeyResolver的类是PrincipalNameKeyResolver,它接受ServerWebExchange的Principal参数,调用Principal.getName()方法。默认情况下,如果KeyResolver没有找到密钥,请求将被拒绝,您可以配置此行为。spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key=truespring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code=xxxx注意:没有配置RequestRateLimiter带有简短注释的以下示例是非法的。spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2,2,#{@userkeyresolver}RedisLimiter介绍Redis实现是基于Stripe的。需要用到spring-boot-starter-data-redis-reactive这个启动器;该算法使用令牌桶。关键业务含义使用redis-rate-limiter.replenishRate一个用户每秒请求多少次不包括丢弃的请求,这个速率就是令牌桶的数量。补充速度redis-rate-limiter.burstCapacity用户允许每秒最大请求数。这个令牌数量就是令牌桶能容纳的数量。设置为0则阻塞所有请求突发容量redis-rate-limiter.requestedTokenssingle请求消耗了多少令牌,这个数量是令牌桶中每次请求获得的令牌数,默认为1次请求消耗令牌如果将replenishRate和burstCapacity的值设置相同,则完成了一个稳定的速度设置。临时突发流量可以设置burstCapacity>replenishRate,在这种情况下,RateLimiter需要在burstCapacity和replenishRate之间留出一些时间。连续两次增加将导致丢弃请求。以下示例配置了redis-rate-limit。速率限制为每秒1个请求,replenishRate=1,requestedTokens=60,burstCapacity=60;spring:cloud:gateway:routes:-id:requestratelimiter_routeuri:https://example.orgfilters:-name:RequestRateLimiterargs:redis-rate-limiter.replenishRate:10redis-rate-limiter.burstCapacity:20redis-rate-limiter.requestedTokens:1上述配置中补充令牌的速度为10,突发容量为20,但在下一秒,只有10个请求可以进入;以下示例配置了一个KeyResolver。只需从请求参数中获取用户(生产环境不推荐),@BeanKeyResolveruserKeyResolver(){returnexchange->Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));}也可以定义你自己的RateLimiter,作为一个bean,只需在下面的配置中实现RateLimiter接口。您可以使用SpEL表达式按名称引用bean。{@myRateLimiter}是一个引用名为myRateLimiter的bean的表达式。以下示例定义了一个rateLimiter并使用自定义KeyResolver.spring:cloud:gateway:routes:-id:requestratelimiter_routeuri:https://example.orgfilters:-name:RequestRateLimiterargs:rate-limiter:"#{@myRateLimiter}"key-resolver:"#{@userKeyResolver}"魔方限流配置如下,限制所有请求。keyvalue设置值replenishRate20的原因是每个用户每秒20burstCapacity4040,每秒请求数突然增加;requestedTokens1为每个连接消耗1个令牌;源码分析:RequestRateLimiterGatewayFilterFactorypublicGatewayFilterapply(Configconfig){KeyResolverresolver=getOrDefault(config.keyResolver,defaultKeyResolver);RateLimiter