✨✨个人主页:沫洺的主页
系列专栏: JavaWeb专栏 JavaSE专栏 Java基础专栏vue3专栏
MyBatis专栏Spring专栏SpringMVC专栏SpringBoot专栏
Docker专栏Reids专栏MQ专栏SpringCloud专栏
如果文章对你有所帮助请留下三连✨✨
衔接上篇: [Spring Cloud] Hystrix通过配置文件统一设置参数/与OpenFeign结合使用_沫洺的博客-CSDN博客
GateWay说明文档: Index of /spring-cloud-gateway/docs
传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。那有了网关之后,能够起到怎样的改善呢?
网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务,所以,使用网关的好处在于:
(1)简化客户端的工作。网关将微服务封装起来后,客户端只需同网关交互,而不必调用各个不同服务;
(2)降低函数间的耦合度。 一旦服务接口修改,只需修改网关的路由策略,不必修改每个调用该函数的客户端,从而减少了程序间的耦合性
(3)解放开发人员把精力专注于业务逻辑的实现。由网关统一实现服务路由(灰度与ABTest)、负载均衡、访问控制、流控熔断降级等非业务相关功能,而不需要每个服务 API 实现时都去考虑
但是 API 网关也存在不足之处,在微服务这种去中心化的架构中,网关又成了一个中心点或瓶颈点,它增加了一个我们必须开发、部署和维护的高可用组件。正是由于这个原因,在网关设计时必须考虑即使 API 网关宕机也不要影响到服务的调用和运行,所以需要对网关的响应结果有数据缓存能力,通过返回缓存数据或默认数据屏蔽后端服务的失败。
在服务的调用方式上面,网关也有一定的要求,API 网关最好是支持 I/O 异步、同步非阻塞的,如果服务是同步阻塞调用,可以理解为微服务模块之间是没有彻底解耦的,即如果A依赖B提供的API,如果B提供的服务不可用将直接影响到A不可用,除非同步服务调用在API网关层或客户端做了相应的缓存。因此为了彻底解耦,在微服务调用上更建议选择异步方式进行。而对于 API 网关需要通过底层多个细粒度的 API 组合的场景,推荐采用响应式编程模型进行而不是传统的异步回调方法组合代码,其原因除了采用回调方式导致的代码混乱外,还有就是对于 API 组合本身可能存在并行或先后调用,对于采用回调方式往往很难控制。
流量网关和服务网关在系统整体架构中所处的位置如上图所示,
流量网关(如Nignx)是指提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控等。
而微服务网关(如Spring Cloud Gateway)是指与业务紧耦合的、提供单个业务域级别的策略,如服务治理、身份认证等。也就是说,流量网关负责南北向流量调度及安全防护,微服务网关负责东西向流量调度及服务治理。
(1)Kong 网关:Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑
(2)Zuul1.x 网关:Zuul 1.0 的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况
(3)gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。
(4)Zuul 2.x:性能与 gateway 差不多,基于非阻塞的,支持长连接,但 SpringCloud 没有集成 zuul2 的计划,并且 Netflix 相关组件都宣布进入维护期,前景未知。
综上,gateway 网关更加适合 SpringCloud 项目,而从发展趋势上看,gateway 替代 zuul 也是必然的。
父模块pom声明
spring-cloud-gateway org.springframework.cloud spring-cloud-dependencies ${spring.cloud.version} pom import 创建子模块spring-cloud-gateway
添加依赖
org.springframework.boot spring-boot-starter-webflux org.springframework.cloud spring-cloud-starter-gateway pom.xml
注意:一定要排除掉 spring-boot-starter-web 依赖,否则启动报错
使用spring-boot-starter-webflux功能和web一样,但是webflux异步框架
4.0.0 com.moming spring-cloud-root 0.0.1-SNAPSHOT ../pom.xml spring-cloud-gateway org.springframework.boot spring-boot-starter-webflux org.springframework.cloud spring-cloud-starter-gateway org.projectlombok lombok true org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok 添加配置
#标识 spring.cloud.gateway.routes[0].id = route1 #配置路由规则 spring.cloud.gateway.routes[0].predicates[0] = Path=/test/** #转发时过滤test,若路由为/test/api/**,StripPrefix=2代表过滤/test/api spring.cloud.gateway.routes[0].filters[0] = StripPrefix=1 #如果符合上面的规则,流量就打到这个网址 spring.cloud.gateway.routes[0].uri = http://httpbin.org
介绍一个网址: httpbin.org(为开发者提供的公开的域名,可以有效测试http协议相关内容)
调试http请求时,能直接看出来响应内容
简单使用一下,如下图get请求
访问
参考文章: Spring Cloud Gateway夺命连环10问?
在介绍 Spring Cloud Gateway 的配置项之前,我们先了解几个 Spring Cloud Gateway 的核心术语:
断言(Predicate):参照 Java8 的新特性Predicate,允许开发人员匹配 HTTP 请求中的任何内容,比如请求头或请求参数或请求路径,最后根据匹配结果返回一个布尔值。
路由(route):由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则转发到该路由。
过滤器(filter):可以在返回请求之前或之后修改请求和响应的内容。
Route 主要由 路由id、目标uri、断言集合和过滤器集合组成,这些属性到底有什么作用。
(1)id:路由标识,要求唯一,名称任意(默认值 uuid,一般不用,需要自定义)
(2)uri:请求最终被转发到的目标地址
(3)order: 路由优先级,数字越小,优先级越高
(4)predicates:断言数组,即判断条件,如果返回值是boolean,则转发请求到 uri 属性指定的服务中
(5)filters:过滤器数组,在请求传递过程中,对请求做一些修改
官方断言使用说明
Predicate 来自于 Java8 的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
Predicate 可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。Spring Cloud Gateway 内置了许多 Predict,这些 Predict 的源码在 org.springframework.cloud.gateway.handler.predicate 包中,有兴趣可以阅读一下。内置的一些断言如下图:
上面我们已经使用过Path(请求path校验条件断言:Path=/test/**)
接下来使用一下Query请求参数校验条件断言
#标识 spring.cloud.gateway.routes[0].id = route1 #配置路由规则 spring.cloud.gateway.routes[0].predicates[0] = Path=/test/** #匹配请求参数的断言,url后一定要有color参数 ?color=red spring.cloud.gateway.routes[0].predicates[1] = Query=color #转发时过滤test,若路由为/test/api/**,StripPrefix=2代表过滤/test/api spring.cloud.gateway.routes[0].filters[0] = StripPrefix=1 #如果符合上面的规则,流量就打到这个网址 spring.cloud.gateway.routes[0].uri = http://httpbin.org
可以看到url传参必须要有color
若是指定color必须为red配置如下
spring.cloud.gateway.routes[0].predicates[1] = Query=color,red
支持正则,指定re前缀,通过"."代表一个字符
spring.cloud.gateway.routes[0].predicates[1] = Query=color,re.
Header(请求header校验条件断言)
spring.cloud.gateway.routes[0].predicates[1] = Header=tokenId,123
官方案例,必须为数字
spring.cloud.gateway.routes[0].predicates[1] = Header=X-Request-Id,\\d+
其他断言规则使用同理
内置局部过滤器
StripPrefixGatewayFilterFactory(用于截断原始请求的路径)
spring.cloud.gateway.routes[0].filters[0] = StripPrefix=1
官网过滤器使用说明
- PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
Gateway 过滤器从作用范围可分为两种:
- GatewayFilter:应用到单个路由或者一个分组的路由上(需要在配置文件中配置)
- GlobalFilter:应用到所有的路由上(无需配置,全局生效)
(1)局部过滤器 GatewayFilter:
Spring Cloud Gateway 中内置了许多的局部过滤器,如下图
局部过滤器需要在指定路由配置才能生效,默认是不生效的。
接下来例举几个常用的
AddResponseParameterGatewayFilterFactory(前置过滤器)
spring.cloud.gateway.routes[0].id = route1 spring.cloud.gateway.routes[0].predicates[0] = Path=/test/** spring.cloud.gateway.routes[0].filters[0] = StripPrefix=1 #前置过滤器,会在请求后端服务接口之前增加一个参数,url会多出来参数color=red spring.cloud.gateway.routes[0].filters[1] = AddRequestParameter=color,red spring.cloud.gateway.routes[0].uri = http://httpbin.org
AddRequestHeaderGatewayFilterFactory(前置过滤器)
spring.cloud.gateway.routes[0].filters[2] = AddRequestHeader=name,moming
AddResponseHeaderGatewayFilterFactory(后置过滤器)
spring.cloud.gateway.routes[0].filters[3] = AddResponseHeader=recruitment,[email protected]
(2)全局过滤器
全局过滤器应用到全部路由上,无需开发者配置,Spring Cloud Gateway也内置了一些全局过滤器
GlobalFilter的功能其实和GatewayFilter是相同的,只是GlobalFilter的作用域是所有的路由配置,而不是绑定在指定的路由配置上。多个GlobalFilter可以通过@Order或者getOrder()方法指定每个GlobalFilter的执行顺序,order值越小,GlobalFilter执行的优先级越高。
#全局过滤器 spring.cloud.gateway.default-filters[0]=AddRequestHeader=vsersion,1.0