文章已收录到我的Github精选,欢迎Star:github.com/yehongzhi/l…
写在前面
前一篇文章写了Gateway的Predicate(用于路由转发),那么这篇文章就介绍另一个主要的核心,那就是Filter(过滤器)。
过滤器有什么作用呢?工作流程是怎么样的呢?请看下图:
从图中很明显可以看出,在请求后端服务前后都需要经过Filter,于是乎Filter的作用就明确了,在PreFilter(请求前处理)可以做参数校验、流量监控、日志记录、修改请求内容等等,在PostFilter(请求后处理)可以做响应内容修改。
过滤器
Filter分为局部和全局两种:
- 局部Filter(GatewayFilter的子类)是作用于单个路由。如果需要使用全局路由,需要配置Default Filters。
- 全局Filter(GlobalFilter的子类),不需要配置路由,系统初始化作用到所有路由上。
局部过滤器
SpringCloud Gateway内置了很多路由过滤器,他们都是由GatewayFilter的工厂类产生。
AddRequestParameter GatewayFilter
该过滤器可以给请求添加参数。
比如我在consumer服务有一个带有userName
参数的接口,我想请求网关路由转发的时候给加上一个userName=yehongzhi
的参数。
1 | less复制代码@RequestMapping(value = "/getOrder",method = RequestMethod.GET) |
配置如下:
1 | yaml复制代码spring: |
那么当我请求网关时,输入http://localhost:9201/getOrder
,我们能看到默认加上的userName。
StripPrefix GatewayFilter
该过滤器可以去除指定数量的路径前缀。
比如我想把请求网关的路径前缀的第一级去掉,就可以这样配置实现:
1 | yaml复制代码spring: |
当请求路径http://localhost:9201/consumer/getDetail/1
,能获得结果。
相当于请求http://localhost:8081/getDetail/1
,结果是一样的。
PrefixPath GatewayFilter
该过滤器与上一个过滤器相反,是给原有的路径加上指定的前缀。
1 | yaml复制代码spring: |
当请求http://localhost:9201/getUserInfo/1
时,跟请求http://localhost:8081/consumer/getUserInfo/1
是一样的。
Hystrix GatewayFilter
网关当然有熔断机制,所以该过滤器集成了Hystrix,实现了熔断的功能。怎么使用呢?首先需要引入Hystrix的maven依赖。
1 | xml复制代码<dependency> |
在gateway服务添加fallback()方法
1 | kotlin复制代码@RestController |
在网关服务的配置如下,对GET请求方式的请求路由转发出错时,会触发服务降级:
1 | yaml复制代码spring: |
这时我们把8081
的服务停止,让网关请求不到对应的服务,从而触发服务降级。
RequestRateLimiter GatewayFilter
该过滤器可以提供限流的功能,使用RateLimiter实现来确定是否允许当前请求继续进行,如果请求太大默认会返回HTTP 429-太多请求状态。怎么用呢?首先还是得引入Maven依赖。
1 | xml复制代码<dependency> |
接着增加个配置类。
1 | kotlin复制代码@Configuration |
然后配置如下,对GET方式的请求增加限流策略:
1 | yaml复制代码spring: |
然后启动服务,连续请求地址http://localhost:9201/getDetail/1
,就会触发限流,报429错误。
因为内置的过滤器实在是太多了,这里就不一一列举了,有兴趣的同学可以到官网自行学习。
自定义局部过滤器
如果内置的局部过滤器不能满足需求,那么我们就得使用自定义过滤器,怎么用呢?下面用一个例子,我们自定义一个白名单的过滤器,userName在白名单内的才可以访问,不在白名单内的就返回401错误码(Unauthorized)。
局部过滤器需要实现GatewayFilter和Ordered接口,代码如下:
1 | typescript复制代码public class WhiteListGatewayFilter implements GatewayFilter, Ordered { |
接着再定义一个过滤器工厂,注入到Spring容器中,代码如下:
1 | typescript复制代码@Component |
最后,我们可以在application.yaml配置文件中加上配置使用:
1 | yaml复制代码spring: |
接着启动项目,先请求localhost:9201/getDetail/1
,不带userName,按预期会返回401,不能访问。
请求带有userName=yehongzhi
的地址http://localhost:9201/getDetail/1?userName=yehongzhi
,是在白名单内的,所以能正常访问。
全局过滤器
全局过滤器在系统初始化时就作用于所有的路由,不需要单独去配置。全局过滤器的接口定义类是GlobalFilter
,Gateway本身也有很多内置的过滤器,我们打开类图看看:
我们拿几个比较有代表性的来做介绍,比如负载均衡的全局过滤器LoadBalancerClientFilter
。
LoadBalancerClientFilter
该过滤器会解析到以lb://
开头的uri,比如这样的配置:
1 | yaml复制代码spring: |
这个全局过滤器就会取到consumer这个服务名,然后通过LoadBalancerClient
获取到ServiceInstance
服务实例。根据获取到的服务实例,重新组装请求的url。
这就是一个全局过滤器应用的例子,它是作用于全局,而且并不需要配置。下面我们探索一下自定义全局过滤器,假设需要统计用户的IP地址访问网关的总次数,怎么做呢?
自定义全局过滤器
自定义全局过滤器需要实现GlobalFilter
接口和Ordered
接口。
1 | java复制代码@Component |
启动项目,然后请求服务,可以看到控制台打印结果。
1 | 复制代码IP地址:192.168.1.4,访问次数:1 |
总结
通过上一篇的Predicates和这篇的Filters基本上把服务网关的功能都实现了,包括路由转发、权限拦截、流量统计、流量控制、服务熔断、日志记录等等。所以网关对于微服务架构来说,网关服务是一个非常重要的部分,有很多一线的互联网公司还会自研服务网关。因此掌握服务网关对于后端开发可以说是必备技能,感谢大家的阅读。
觉得有用就点个赞吧,你的点赞是我创作的最大动力~
我是一个努力让大家记住的程序员。我们下期再见!!!
能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!
本文转载自: 掘金