基本介绍
Spring Cloud Gateway是基于Spring生态系统之上构建的API网关,包括:Spring 5.x,Spring Boot 2.x和Project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性,监视/指标,限流等。
- 什么是服务网关
API Gateway(APIGW / API 网关),顾名思义,是系统对外的唯一入口。API网关封装了系统内部架构,为每个客户端提供定制的API。 近几年来移动应用与企业间互联需求的兴起。从以前单一的Web应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。 这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着微服务架构概念的提出,API网关成为了微服务架构的一个标配组件。 - 为什么要使用网关
微服务的应用可能部署在不同机房,不同地区,不同域名下。此时客户端(浏览器/手机/软件工具)想 要请求对应的服务,都需要知道机器的具体 IP 或者域名 URL,当微服务实例众多时,这是非常难以记忆的,对 于客户端来说也太复杂难以维护。此时就有了网关,客户端相关的请求直接发送到网关,由网关根据请求标识 解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就全部交由网关来操作了。 - 核心概念
路由(Route):路由是网关最基础的部分,路由信息由 ID、目标 URI、一组断言和一组过滤器组成。如果断言 路由为真,则说明请求的 URI 和配置匹配。
断言(Predicate):Java8 中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是 Spring 5.0 框架中 的 ServerWebExchange。Spring Cloud Gateway 中的断言函数允许开发者去定义匹配来自于 Http Request 中的任 何信息,比如请求头和参数等。
过滤器(Filter):一个标准的 Spring Web Filter。Spring Cloud Gateway 中的 Filter 分为两种类型,分别是 Gateway Filter 和 Global Filter。过滤器将会对请求和响应进行处理
使用网关
添加依赖
<!-- spring cloud gateway 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置文件
server:
port: 8080
spring:
application:
name: ruoyi-gateway
cloud:
gateway:
routes:
# 系统模块
- id: ruoyi-system
uri: http://localhost:9201/
predicates:
- Path=/system/**
filters:
- StripPrefix=1
本文章基于ruoyi-cloud整理而来,目前已经存在的ruoyi-gateway网关服务,用于路由转发、异常处理、限流、降级、接口、鉴权等等。
路由规则
Spring Cloud Gateway创建Route对象时, 使用RoutePredicateFactory创建Predicate对象,Predicate对象可以赋值给Route。
- Spring Cloud Gateway包含许多内置的Route Predicate Factories
- 所有这些断言都匹配 HTTP 请求的不同属性
- 多个Route Predicate Factories可以通过逻辑与(and)结合起来一起使用
路由断言工厂RoutePredicateFactory包含的主要实现类如图所示,包括Datetime、请求的远端地址、路由权重、请求头、Host 地址、请求方法、请求路径和请求参数等类型的路由断言。
Datetime
匹配日期时间之后发生的请求
spring:
application:
name: ruoyi-gateway
cloud:
gateway:
routes:
- id: ruoyi-system
uri: http://localhost:9201/
predicates:
- After=2021-02-23T14:20:00.000+08:00[Asia/Shanghai]
Host
匹配主机名的列表
spring:
application:
name: ruoyi-gateway
cloud:
gateway:
routes:
- id: ruoyi-system
uri: http://localhost:9201/
predicates:
- Host=**.somehost.org,**.anotherhost.org
Path
匹配请求路径
spring:
application:
name: ruoyi-gateway
cloud:
gateway:
routes:
- id: ruoyi-system
uri: http://localhost:9201/
predicates:
- Path=/system/**
除了以上路由规则外,还有其他的配置规则,可以到官网查看,这里就不一一举例了;
路由配置
在spring cloud gateway中配置uri有三种方式,包括
1、 websocket配置方式
spring:
cloud:
gateway:
routes:
- id: ruoyi-api
uri: ws://localhost:9090/
predicates:
- Path=/api/**
2、http地址配置方式
spring:
cloud:
gateway:
routes:
- id: ruoyi-api
uri: http://localhost:9090/
predicates:
- Path=/api/**
3、注册中心配置方式
spring:
cloud:
gateway:
routes:
- id: ruoyi-api
uri: lb://ruoyi-api
predicates:
- Path=/api/**
熔断降级
Spring Cloud中的熔断(Circuit Breaker)和降级(Fallback)是用于处理服务调用失败的两种常见的容错机制。
熔断(Circuit Breaker):是指当服务调用失败时,为了防止错误的传播和持续对故障服务的调用,可以通过在客户端实现熔断器来实现。熔断器会在服务调用失败时打开,并在一段时间内拒绝对服务的调用。在此期间,熔断器会快速返回预先定义的默认值或错误信息,而不会真正调用服务。当服务调用失败次数达到一定阈值后,熔断器会切换到半开状态,允许部分服务调用通过以检测服务是否恢复正常。如果服务调用成功,则将熔断器关闭,恢复对服务的正常调用。
举个例子:
如果服务B调用服务D,一旦调用成功率低于90%,我们就可以认为现在服务有问题,程序为了整体的稳定性,所以暂时(断开)停止服务一段时间,以保证程序可用时再被使用。
B调用D 调10次,仅成功8次?这不行啊,那我们先暂停调用D,让D缓一缓。
D停止使用期间,服务会返回给客户一个预设的响应结果,比如一个缓存数据,或者调用别的服务给出推荐内容。
但D不会一直被停用,会有一定的策略验证D当前运行状态。比如我们会每分钟试探性的调用D服务5次,若都成功了,则下一分钟调用D服务10次,直至确定D服务恢复正常,自动停止熔断。
降级(Fallback):是指当服务调用失败时,为了避免对用户造成不必要的等待和影响,可以提供一个备用的服务或数据来代替失败的服务。降级可以是静态的,即提供一个固定的默认值;也可以是动态的,即根据系统当前状态或配置来提供不同的降级策略。降级可以是全局的,即对所有调用都生效;也可以是局部的,即只对特定的服务调用生效。
通俗的讲,当系统负载过高或部分服务不可用时,为了保证核心功能的稳定性,临时屏蔽某些非关键服务或采用简化的备用逻辑,提供有限但可靠的服务。
例如购物节前夕,为了确保客户有更好的购物体验,购物系统会将软件中不常用的功能,比如个性化装扮,趣味小游戏暂时关闭,用更多的空闲运行空间,以缓解订单系统的压力,确保整个系统的问题。
熔断和降级可以结合使用,通过熔断器实现服务调用的熔断和降级策略,提高系统的容错性和稳定性。在Spring Cloud中,可以使用Hystrix等熔断器来实现熔断和降级的功能。
Spring cloud gateway配合Hystrix使用已经拥有了熔断、降级的能力,但是有时我们在其他开源系统中也能看到使用Sentinal来进行限流、熔断、降级的,这里就需要说一下两者的区别,Sentinal是阿里开源的网关组件,其能力是经过阿里双十一等购物节考验的,支持的网关场景比Hystrix要多很多,Hystrix则是只支持一些简单的、基础的网关功能,能满足一些简单场景下的限流和熔断;所以实际项目中二者具体要用哪个,要更具实际应用场景来说,不能简单的说孰好孰坏;
除了以上cloud gateway的用法之外,还有限流配置、跨域配置、黑白名单配置、全局过滤器等;