1. 前言
当前通过Eureka、Nacos解决了服务注册和服务发现问题,使用Spring Cloud LoadBalance解决了负载均衡的需求,同时借助OpenFeign实现了远程调用。然而,现有的微服务接口都直接对外暴露,容易被外部访问。为保障对外服务的安全性,通常在服务端实现的微服务接口会带有一定的权限校验机制。由于应用拆分成多个微服务,每个微服务都需要实现权限校验逻辑,导致当逻辑需要修改时,需要在多个应用中进行修改,增加了开发人员的负担。
- 1. 办事效率低
- 2. 增加了员⼯的⼯作流程
接下来我将会介绍一门新的技术: API网关 SpringCloudGateway
在微服务架构中,API 网关扮演着至关重要的角色,它是客户端和后端服务之间的门面,负责统一处理所有的请求和响应。Spring Cloud Gateway作为Spring Cloud生态系统中的一个全新项目,提供了强大而灵活的方式来构建 API 网关服务。本文将深入介绍Spring Cloud Gateway的功能、特点以及如何应用于微服务架构中。
2. 功能和特点
Spring Cloud Gateway提供了丰富的功能和特性,其中包括:
- 动态路由: 可以根据需求动态地将请求路由到相应的后端服务,实现请求的分发和转发。
- 权限控制: 可以通过实现对请求的安全控制,包括认证、鉴权、请求加密等功能,保障系统的安全性。
- 负载均衡: 集成了负载均衡的功能,可以将请求分发到多个后端服务实例中,提高系统的可用性和性能。
- 断路器: 支持断路器模式,可以在后端服务不可用时进行降级处理,避免整个系统的崩溃。
- 统一的认证和授权: 可以集成统一的认证和授权机制,保护系统的安全性。
- 监控和日志: 支持监控和日志记录,帮助开发者排查问题和优化系统性能。
-
过滤器处理: 可以通过自定义的过滤器对请求进行预处理、后处理、权限控制、日志记录等操作,实现对请求的统一管理和处理。
-
限流:可以通过过滤器和流量算法实现对流量的控制,防止流量过大导致系统崩溃。请求流量过⾼时, 按照⽹关中配置微服务能够接受的流量进⾏放⾏, 避免服务压力过大
类似前台的⼯作1. 权限控制: ⾝份验证。2. 动态路由: 根据外来客⼾的需求, 把客⼾带到指定的部⻔去处理。3. 负载均衡: ⼀个部⻔有很多⼈时, 前台会帮客⼾选择具体某个⼈处理。4. 限流: 公司到访客⼾较多时, 进⾏流量限制, ⽐如告知明天再来。
3. 什么是API网关?
4. 简单的使用步骤
3.1 创建一个新的模块
3.2 引入依赖
<!--引入spring_cloud_gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos的依赖用于动态路由-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
引入nocos的依赖和负载均衡的依赖就是因为我们的动态路由控制和负载均衡均根据二者实现的。
3.3 修改配置文件
server: port: 10030 spring: application: name: gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 # 配置路由的规则 gateway: # 这里配置了一个路由规则,将请求转发到名为"order-service"的服务上。 # 当请求的路径以"/order/"开头时,会被路由到"order-service"服务上。 routes: - id: order-service #路由规则id,随便起不重复即可 # lb 表示负载均衡(Load Balancing)的意思。它告诉Spring Cloud Gateway使用负载均衡的方式将请求分发到多个实例中。 uri: lb://order-service # 指定路由到哪个机器里 # 条件 predicates: - Path=/order/**,/feign/** # ,后面配置多个路径
- id : ⾃定义路由ID, 保持唯⼀
- uri: ⽬标服务地址, ⽀持普通URI 及 lb://应⽤注册服务名称 . lb表⽰负载均衡, 使⽤ lb:// ⽅
- 式表⽰从注册中⼼获取服务地址.
- predicates: 路由条件, 根据匹配结果决定是否执⾏该请求路由, 上述代码中, 我们把符合Path规则的 ⼀切请求, 都代理到uri参数指定的地址.
4. 路由断言工厂
spring:
cloud:
gateway:
routes:
- id: after-route
uri: https://example.org
predicates:
- After=2024-06-05T12:00:00+08:00[Asia/Shanghai]
例如上述 -After就是路由断言工厂,也就是路由的条件符合条件才可以访问。
名称 | 说明 | 示例 |
After
|
这个⼯⼚需要⼀个⽇期时间(Java
的 ZonedDateTime对象), 匹配指
定⽇期之后的请求
|
predicates:
-
After=2017-01-20T17:42:47.789-
07:00[America/Denver]
|
Before |
匹配指定⽇期之前的请求
|
predicates:
-
Before=2017-01-20T17:42:47.789-
07:00[America/Denver]
|
Between | 匹配两个指定时间之间的请求,
datetime2
的参数必须在 datetime1 之后
|
predicates:
-
Between=2017-01-20T17:42:47.789-
07:00[America/Denver],
2017-01-
21T17:42:47.789-07:00
[
America/Denver
]
|
Cookie |
请求中包含指定Cookie, 且该 Cookie值符合指定的正则表达式
|
predicates:
-
Cookie=chocolate, ch.p
|
Header |
请求中包含指定Header, 且该 Header值符合指定的正则表达式
|
predicates:
-
Header=X-Request-Id, \d+
|
Host |
请求必须是访问某个host(根据请 求中的Host 字段进⾏匹配)
|
predicates:
-
Host=**.somehost.org,**.anotherhost.or g
|
Method
|
匹配指定的请求⽅式
|
predicates:
-
Method=GET,POST
|
Path
|
匹配指定规则的路径
|
predicates:
-
Path=/red/{segment},/blue/{segment}
|
5. ⽹关过滤器工厂
- 进景区之前需要先安检, 验票(鉴权), 如果今⽇进景区的⼈超过了规定的⼈数, 就会进⾏限流
- 接下来进景区游玩
- 游玩之后, 对景区服务进⾏评价
- GatewayFilter: 应⽤到单个路由或者⼀个分组的路由上.
- GlobalFilter: 应⽤到所有的路由上, 也就是对所有的请求⽣效
GatewayFilter 同 Predicate 类似, 都是在配置文件 application.yml 中配置,每个过滤器的逻辑都是固定的. 比如 AddRequestParameterGatewayFilterFactory 只需要在配置⽂件中写 AddRequestParameter , 就可以为所有的请求添加⼀个参数, 我们先通过⼀个例子来演示GatewayFilter如何使用。
GlobalFilter是一种应用到所有路由上的过滤器,它会对所有的请求生效,而不是仅应用到单个路由或者一个分组的路由上。这意味着,不管是哪个路由,GlobalFilter都会对请求进行处理。
在Spring Cloud Gateway中,GlobalFilter可以用来实现一些全局的功能,比如安全认证、日志记录、请求转发等。与GatewayFilter相比,GlobalFilter的逻辑不是固定的,而是可以自定义的,因此它具有更大的灵活性和功能性。
举个例子,你可以创建一个自定义的GlobalFilter来记录每个请求的访问日志,并将日志信息保存到数据库中。这样无论是哪个路由的请求,都会被这个GlobalFilter捕获并进行相应的处理。
在配置文件application.yml中,GlobalFilter的配置方式与GatewayFilter类似,只需要在其中配置相应的过滤器名称即可。通过这种方式,GlobalFilter会应用到所有的路由上,对所有的请求生效。
演示示例:
6.常见的过滤信息参数设置
名称 | 说明 | 示例 |
AddRequestHeader
|
为当前请求添加Header
|
- AddRequestHeader=X-Request-red, blue
参数: Header的名称及值
|
AddRequestParameter
|
为当前请求添加请求参数
|
- AddRequestParameter=red, blue
参数: 参数的名称及值
|
AddResponseHeader
|
为响应结果添加Header
|
- AddResponseHeader=X-Response-Red, Blue
参数: Header的名称及值
|
RemoveRequestHeader
|
从当前请求删除某个Header
| - RemoveRequestHeader=X-Request-Foo 参数: Header的名称 |
RemoveResponseHeader
|
从响应结果删除某个Header
| - RemoveResponseHeader=X-Response-Foo
参数: Header的名称
|
RequestRateLimiter
|
为当前⽹关的所有请求 执⾏限流过滤, 如果被限流,默认提供了 RedisRateLimiter的限 流实现, 采⽤令牌桶算法实现限流功能. 此处不做
|
filters:
-
name:
RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
redis-rate-limiter.replenishRate
: 令牌填充速度, 即 每秒钟允许多少个请求(不丢弃任何请求) redis-rate-limiter.burstCapacity : 令牌桶容量, 即每秒⽤⼾最⼤能够执⾏的请求数量(不丢弃任何请求). 将此值设置 为零将阻⽌所有请求
redis-rate-limiter.requestedTokens
: 每次请求占⽤⼏个令牌, 默认为 1
。
|
Retry
|
针对不同的响应进⾏重 试. 当后端服务不可⽤ 时, ⽹关会根据配置参数来发起重试请求.
|
filters:
-
name:
Retry
args:
retries: 3
statuses:
BAD_REQUEST
retries: 重试次数, 默认为3
status:HTTP请求返回的状态码, 针对指定状态码进⾏重试. 对应 org.springframework.http.HttpStatus
|
RequestSize |
设置允许接收最⼤请求包的⼤⼩. 如果请求包⼤⼩超过设置的值, 则返回
请求包⼤⼩, 单位为字
节, 默认值为5M.
|
filters:
-
name:
RequestSize
args:
maxSize: 5000000
|
默认过滤器 |
添加⼀个filter并将其应⽤于所有路由, 这个属性需要⼀个filter的列表,
|
总结:
随着微服务架构的广泛应用,API 网关成为了系统架构中的关键组件,用于统一处理所有的请求和响应,实现了诸如动态路由、权限控制、负载均衡、断路器等功能。Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个全新项目,提供了强大而灵活的方式来构建 API 网关服务。
Spring Cloud Gateway 的功能和特点包括:
- 动态路由:根据需求动态地将请求路由到相应的后端服务,实现请求的分发和转发。
- 权限控制:通过实现对请求的安全控制,包括认证、鉴权、请求加密等功能,保障系统的安全性。
- 负载均衡:集成了负载均衡的功能,可以将请求分发到多个后端服务实例中,提高系统的可用性和性能。
- 断路器:支持断路器模式,可以在后端服务不可用时进行降级处理,避免整个系统的崩溃。
- 统一的认证和授权:可以集成统一的认证和授权机制,保护系统的安全性。
- 监控和日志:支持监控和日志记录,帮助开发者排查问题和优化系统性能。
在使用 Spring Cloud Gateway 进行开发时,主要包括以下步骤:
- 创建一个新的模块,并引入相应的依赖,其中包括 Spring Cloud Gateway 和用于动态路由的注册中心(如 Nacos),以及负载均衡的依赖。
- 修改配置文件,配置网关的端口、注册中心地址以及路由规则等信息。
- 配置路由的规则,通过配置文件指定请求的路径和目标服务地址,实现请求的转发。
- 可以根据需要使用路由断言工厂,实现更加精细化的路由控制。
- 配置网关过滤器工厂,实现对请求的预处理和后处理,包括添加请求头、请求参数、限流等功能。
对于限流算法,常见的有固定窗口、滑动窗口、漏桶算法和令牌桶算法。其中,令牌桶算法是一种常用的限流算法,通过固定容量的令牌桶和固定速率产生令牌来限制请求的处理速率,允许一定程度的突发流量。