微服务 过滤器 集成Sentinel实现网关限流
- Gateway - -> 过滤器Filter
- 局部路由过滤器
- 使用局部过滤器
- 全局过滤器
- 使用全局过滤器
- 集成Sentinel实现网关限流
- 网关限流
- API分组限流
Gateway - -> 过滤器Filter
过滤器就是在请求的传递过程中,对请求和响应做一些手脚.
在Gateway中, Filter的生命周期只有两个:“pre”和“post”"。
.PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
.POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTPHeader、收集统计信息和指标、将响应从微服务发送给客户端等。
在Gateway中,Filter的作用范围两种:
.GatewayFilter:应用到单个路由或者一个分组的路由上。
.GlobalFilter:应用到所有的路由上
局部路由过滤器
第一步:编写配置文件
第二步:创建局部过滤器类
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {
//解析参数
public TimeGatewayFilterFactory(){
super(Config.class);
}
//读取配置文件中的参数 赋值到 配置类中
public List<String> shortcutFieldOrder(){
return Arrays.asList("show");
}
//拦截到之后就会调用apply方法,把创建对象时候反射创建出来的config传入进来
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//前置的逻辑
System.out.println("前置逻辑");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
//后置的逻辑
System.out.println("后置逻辑");
}));
}
};
}
//将解析好的参数注入其中
@Setter
@Getter
static class Config{
private boolean show;
}
}
使用局部过滤器
假设我们给商品类创建一个局部过滤器,当传入参数为true的时候,控制台内返回网关转发到服务的时间
创建一个过滤器类:
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {
//解析参数
public TimeGatewayFilterFactory(){
super(Config.class);
}
//读取配置文件中的参数 赋值到 配置类中
public List<String> shortcutFieldOrder(){
return Arrays.asList("show");
}
//拦截到之后就会调用apply方法,把创建对象时候反射创建出来的config传入进来
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if(!config.show){
return chain.filter(exchange);
}
//前置的逻辑
long start = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("请求耗时:"+(System.currentTimeMillis()-start));
}));
}
};
}
//将解析好的参数注入其中
@Setter
@Getter
static class Config{
private boolean show;
}
}
运行结果:
当参数为true的时候
如果访问别的模块,控制台是不会返回的,这就是局部过滤
当参数为false的时候
全局过滤器
全局过滤器作用于所有路由,无需配置,通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。
假设我们现在有一个需求:实现统一鉴权的功能,我们需要在网关判断请求是否包含token且,如果没有则不转发路由,有则正常逻辑。
使用全局过滤器
1.编写全局过滤类
@Component
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//前置逻辑
//获取请求中的token信息,验证token是否有效,如果无效拦截请求,
String token = exchange.getRequest().getQueryParams().getFirst("token");
if(StringUtils.isEmpty(token)||!"123".equals(token)){
System.out.println("鉴定失败");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
运行结果:
集成Sentinel实现网关限流
网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们本次采用前
面学过的Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进
行限流。
从1.6.0版本开始,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:
. route维度:即在spring配置文件中配置的路由条目,资源名为对应的routeld
·自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组
实现步骤:
1.添加依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
2.添加配置文件
cloud:
sentinel:
transport:
port: 9999
dashboard: localhost:8080
运行结果
那么问题来了,如果给网关限流了,那还有必要给接口限流吗?
答案是一定的,网关限流是为了控制通过网关转发到各个微服务的流量,为了防止网关因为流量过大而损坏,但是万一该微服务中被其它若干个别的模块调用的时候,同样也会遭受到很大的压力,容易造成该模块服务器的损坏
总结一句话
网关限流是为了控制访问该微服务的总体流量,但没有办法控制访问该其中特定接口的流量,接口同样也要增加限流
网关限流
API分组限流
第一步:创建API分组
创建流控: