基于gateway网关实现限流
前言
在前面的限流方案介绍中,我们谈到了网关在微服务体系架构中的重要作用,网关不经具备大家熟知的动态路由,请求拦截等功能外,还可以基于网关实现分布式环境下的限流,下面我们以gatway为例,用代码进行实现一下
实现原理
- 所有经过网关代理的请求会被网关进行拦截
- 基于拦截到的请求,可以以IP、请求参数、方法名等作为限流的维度
- 既然是限流,必然存在一个存储请求信息的地方,我们这里选用redis,简单高效,只需配置一定的策略即可
代码实现逻辑
1、添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
这里只引入了关键的依赖,简单说明下,这里沿用之前的使用gateway整合时的框架demo进行演示,注册中心使用eureka,整个环境包括3个工程,eureka-server,gateway工程和一个被gateway代理的微服务模块
2、限流策略配置类
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;
@Configuration
public class HostAddrKeyResolver {
//限流策略数据存储在redis中
@Bean("redisRateLimiter")
@Primary
public RedisRateLimiter redisRateLimiter(){
return new RedisRateLimiter(1,1);
}
//基于IP地址进行限流
@Bean("remoteAddrKeyResolver")
@Primary
public KeyResolver remoteAddrKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
//基于hostName地址进行限流
@Bean("remoteHostNameKeyResolver")
@Primary
public KeyResolver remoteHostNameKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostName());
}
//根据请求参数进行限流
@Bean("remoteUserKeyResolver")
@Primary
public KeyResolver remoteUserKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
}
使用gateway进行限流,其配置主要包括2部分,一个是配置KeyResolver,可以将这个KeyResolver理解为不同类型的限流策略配置,比如是针对IP进行限流,还是基于请求参数进行限流,这样的话你就需要在spring容器中提供不同的bean
第二是RateLimiter,即限流算法的配置,前面我们聊到了常用 的请求算法,像令牌桶算法,比如你允许每秒有多少个请求通过,某一时刻桶中有多少个请求等,参照上面的配置类
3、限流配置类
这里我们采用了配置的方式,替代了在yml里面进行配置,在之前我们有过介绍,最后只需要将上面的限流策略配置类配置到filter里面即可生效
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
@Configuration
public class GatewayConfiguration {
//@Autowired
//private AuthFilter authFilter;
@Autowired
private KeyResolver remoteAddrKeyResolver;
@Autowired
private RateLimiter redisRateLimiter;
@Bean
@Order
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
//多个路由规则就添加多个route
.route(r ->
r.path("/pay/payment/**")
.filters(f ->
f.stripPrefix(1).
//添加自定义的filter
requestRateLimiter(c -> {
c.setKeyResolver(remoteAddrKeyResolver);
c.setRateLimiter(redisRateLimiter);
c.setStatusCode(HttpStatus.BAD_GATEWAY);
})
)
.uri("lb://cloud-payment-service")
).build();
}
}
4、效果测试
分别启动相关的微服务模块,浏览器输入:
http://localhost:8721/pay/payment/get/11
每秒一次,可以正常访问得到响应结果,如果我们快速刷新页面,
从这里可以看到被限流了
当然我们在使用的时候,针对同一个路由,可以组合多种限流策略,有兴趣的同学可以继续研究,本篇到此结束,最后感谢观看!
本文地址:https://blog.csdn.net/zhangcongyi420/article/details/108874233
推荐阅读
-
基于Nacos实现Spring Cloud Gateway实现动态路由的方法
-
Spring Cloud Gateway 服务网关快速实现解析
-
基于Hystrix实现限流
-
【SpringCloudAlibaba专题】spring cloud gateway结合nacos实现sentinel动态限流值url参数模式
-
Spring-Cloud-Gateway基于令牌桶算法进行请求次数限流
-
基于Nginx实现服务访问限流
-
基于拦截器Interceptor+Redis实现接口限流
-
详解基于redis实现的四种常见的限流策略
-
基于Redis的限流器的实现(示例讲解)
-
gateway集成sentinel网关限流