SpringCloud GateWay——微服务网关
1.什么是网关
在微服务的背景下,一个业务会被拆分为很多个服务,而当这些服务都有不同的ip(可以理解为在不同机器上)。没有网关时,当客户端要请求服务时,请求不同的服务还要编写不同请求地址,而且当多个服务都要安全认证,流量控制,日志,监控等功能时,都需要在每个服务中单独实现,修改起来十分麻烦。
网关就是网络的一个关口,在客户端请求服务端时,就先经过网关,这样前端就只需要把请求发送到网关ip上就可以了,而这个请求要转发到哪个微服务ip,就由我们的网关来确定,并且我们还可以再网关处做对请求做安全认真,流量控制,日志等功能,就不需要一个一个在不同的服务上写了。
简单来说,网关的作用就是:请求转发+请求过滤
网关根据请求,判断应该调用哪个微服务,再讲请求转发过去
2.SpringCloud工作流程(原理)
这是 Spring 官方博客中的一张图,原文地址
客户端向网关发送请求
路由判断:请求先经过网关中的
Gateway Hander Mapping
,在这里作断言(Predicates)判断,把复合断言规则的请求映射到后端服务请求过滤:
GateWay Web Mapping
把请求传入到前置过滤链Pre-Filter
,在前置过滤链中对请求做拦截和修改(如,添加请求头,请求参数,校验参数等),用户可以在自定义过滤链。但在前置过滤链中,最后一个过滤链必是Porxy Filter
(由底层自动实现),他用于把请求发送给服务服务处理: 服务端处理
Porxy Filter
发送过来的请求,将结果返回给网关中的后置过滤链Post Filter
响应过滤:在后置过滤链中,用户可以自定义过滤链,对响应进行处理,
Porxy Filter
是后置过滤链中经过的第一个Filter 用于接受服务端发来的响应。(通常开发情况下,极少会有自定义响应过滤的需求)将响应依次经过
Gateway Web Mapping
和GateWay Hander Mapping
返回给客户端
3.Spring Cloud GateWay断言是什么
断言(Predicate) 就是一个匹配规则。说白了就像一个if判断,符合规则的就是真 不符合的就是假。
在Spring Cloud GateWay中,符合匹配规则的请求就会转发到响应的服务上
断言配置的示例如下,配置了两个路由规则,有一个 predicates 断言配置,当请求 url 中包含 api/thirdparty
,就匹配到了第一个路由 route_thirdparty
。
常见的路由判断规则:
4.路由和断言的关系
一个路由可以有多个断言
只有同时满足断言中的条件时,请求才能转发到路由
当请求同时满足多个断言时,只通过第一个满足的断言
5.GateWay的过滤器有哪些
GateWay的过滤器有两种分类方式:
按过滤顺序分:
前置过滤器
Pre-Fliter :在请求被转发到微服务之前,对请求进行拦截和修改,如:添加请求头,参数校验,日志输出等
后置过滤器
Post-Filter:在微服务把响应发送给客户端之前,对响应进行拦截和修改,如:添加响应头,修改响应体,日志输出等
按生效范围分:
局部过滤器
只在指定的路由生效
全局过滤器
全局路路由生效
局部过滤器
局部过滤器
标红的为常见的
用法
spring:
cloud:
gateway:
routes:
- id: route_member # 第三方微服务路由规则
uri: lb://passjava-member # 负载均衡,将请求转发到注册中心注册的 passjava-member 服务
predicates: # 断言
- Path=/api/member/** # 如果前端请求路径包含 api/member,则应用这条路由规则
filters: #过滤器
- RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的api替换成空
全局过滤器
1.全局过滤器
标红为常见,一般情况下,全局过滤器都是用自定义的,只有那个标红的是常见的。
用法
spring:
cloud:
gateway:
routes:
- id: route_member # 第三方微服务路由规则
uri: lb://passjava-member # 负载均衡,将请求转发到注册中心注册的 passjava-member 服务
predicates: # 断言
- Path=/api/member/** # 如果前端请求路径包含 api/member,则应用这条路由规则
filters: #过滤器
- RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的api替换成空
这里有个关键字
lb
,用到了全局过滤器LoadBalancerClientFilter
,当匹配到这个路由后,会将请求转发到 passjava-member 服务,且支持负载均衡转发,也就是先将 passjava-member 解析成实际的微服务的 host 和 port,然后再转发给实际的微服务。
6.如何自定义过滤器
具体实现参考:我的这篇文章
自定义局部过滤器GateWayFilter
继承父类AbstractGatewayFilterFactory<object>,重写父类方法
子类的名称必须是xxxGateWayFilterFactory(如:testGateWayFilterFactory)
在子类上添加@Component注解
在配置文件中对需要使用该局部过滤器的路由引入该局部过滤器
注意:引入的时候 只需要子类名称的xxx部分,而不需要后面的GateWayFilterFactory
自定义全局过滤器GlobalFilter
实现GlobalFilter接口,如果需要定义过滤器顺序那得再实现Ordered接口
重写接口中的方法
添加@Component注解
全局过滤器只需要实现上面的步骤就可以生效了,无须在配置文件中引入
7.动态路由
7.1 为什么需要动态路由
在微服务项目中,我们把路由规则写在网关服务中,用于路由转发。在网关服务启动时,底层就会把配置文件中的路由规则缓存起来形成一个路由表(一个Map)放到内存中,不会改变,也不会监听变更,所以用nacos的热更新配置也不能实现热更新。所以当我们需要更新路由规则的时候,就得重启网关服务。
要知道网关服务可是所有请求的一个入口,至关重要,随随便便重启网关服务十分危险。动态路由技术就是用来解决这样的问题。
参考文章: