网关(Gateway)是微服务中不可缺少的一部分,它是微服务中提供了统一访问地址的组件,充当了客户端和内部微服务之间的中介。网关主要负责流量路由和转发,将外部请求引导到相应的微服务实例上,同时提供一些功能,如身份认证、授权、限流、监控、日志记录等。
网关的主要作用有以下几个:
为了保护后端微服务免受突发高流量请求的影响,确保系统的稳定和可靠性,所以在网关层必须“限流”操作。
限流是一种流量控制的策略,用于限制系统处理请求的速率或数量,以保护系统免受过载或攻击的影响。通过限制请求的数量或速率,可以平衡系统和资源之间的压力,确保系统在可接受的范围内运行。
限流的常见策略通常有以下几种:
当然,我们也可以在程序中使用多种策略混合限流,以保证内部微服务的稳定性。
了解了网关和限流的相关内容之后,我们以目前主流的网关组件 Spring Cloud Gateway 为例,来实现一下限流功能。
Spring Cloud Gateway 实现限流的方式有两种:
那既然 Spring Cloud Gateway 中已经内置了限流功能,那我们接下来就来看 Spring Cloud Gateway 内置限流是如何实现的?
Spring Cloud Gateway 内置的限流器为 RequestRateLimiter GatewayFilter Factory,官网说明文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-requestratelimiter-gatewayfilter-factory
Spring Cloud Gateway 支持和 Redis 一起来实现限流功能,它的实现步骤如下:
具体实现如下。
在项目的 pom.xml 中,添加以下配置信息(添加 Redis 框架依赖支持):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency>
接下来我们新建一个限流规则定义类,实现一下根据 IP 进行限流的功能,实现示例代码如下:
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;import org.springframework.stereotype.Component;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;@Componentpublic class IpAddressKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { return Mono.just(exchange.getRequest().getRemoteAddress(). getHostString()); }}
这一步其实是在配置限流器的限流参数 KeyResolver,也就是限流功能的依赖“凭证”。
“
PS:当然,我们还可以通过 URL、方法名、用户等进行限流操作,只需要修改此步骤中的限流凭证,也就是 KeyResolver 即可。
”
在网关项目的配置文件中,添加以下配置信息:
spring: cloud: gateway: routes: - id: retry uri: lb://nacos-discovery-demo predicates: - Path=/retry/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 redis-rate-limiter.burstCapacity: 1 keyResolver: '#{@ipAddressKeyResolver}' # spEL表达式 data: redis: host: 127.0.0.1 port: 16379 database: 0
其中,name 必须等于“RequestRateLimiter”内置限流过滤器,其他参数的含义如下:
“
SpEL(Spring Expression Language,Spring 表达式语言)是 Spring 框架中用于提供灵活、强大的表达式解析和求值功能的统一表达式语言。它可以在运行时动态地解析和求值字符串表达式,通常用于配置文件中的属性值、注解、XML 配置等地方。
”
当 Spring Cloud Gateway 配合 Redis 实现限流的时候,它对于 Redis 的版本是有要求的,因为它在限流时调用了一个 Redis 高版本的函数,所以 Redis Server 版本太低,限流无效,Redis Server 最好是 5.X 以上。
最后,我们频繁的访问:http://localhost:10086/retry/test 就会看到如下限流信息:
Spring Cloud Gateway 内置限流功能使用的算法是令牌桶限流算法。
令牌桶限流算法:令牌按固定的速率被放入令牌桶中,桶中最多存放 N 个令牌(Token),当桶装满时,新添加的令牌被丢弃或拒绝。当请求到达时,将从桶中删除 1 个令牌。令牌桶中的令牌不仅可以被移除,还可以往里添加,所以为了保证接口随时有数据通过,必须不停地往桶里加令牌。由此可见,往桶里加令牌的速度就决定了数据通过接口的速度。我们通过控制往令牌桶里加令牌的速度从而控制接口的流量。 令牌桶执行流程如下图所示:
常见的限流算法还有:计数器算法、滑动计数器算法、漏桶算法等,更多介绍参考我之前写个的文章:https://www.javacn.site/interview/springcloud/loadbalancer.html。
Spring Cloud Gateway 执行过程如下图所示:
从图中可以看出,所有的请求来了之后,会先走过滤器,只有过滤器通过之后,才能调用后续的内部微服务,这样我们就可以通过过滤器来控制微服务的调用,从而实现限流功能了。
Spring Cloud Gateway 过滤器是基于令牌桶算法来限制请求的速率,该过滤器根据配置的限流规则,在指定的时间窗口内分配一定数量的令牌,每个令牌代表一个允许通过的请求,当一个请求到达时,如果没有可用的令牌,则请求将被阻塞或拒绝。
令牌桶的执行过程如下:
主流网关组件 Spring Cloud Gateway 实现限流的方式主要有两种:内置限流过滤器和外部限流组件,如 Sentinel、Hystrix 等。而最简单的限流功能,我们只需要使用 Spring Cloud Gateway 过滤器 + Redis 即可(实现),其使用的是令牌桶的限流算法来实现限流功能的。
本文链接:http://www.28at.com/showinfo-26-31548-0.html面试官:网关如何实现限流?
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 深入剖析SpringBoot底层原理
下一篇: C++中的内联函数:提高程序效率