9.4 Spring Cloud Gateway 动态路由
-
默认情况下,Spring Cloud Gateway 会根据服务注册中心(例如 Eureka Server)中维护的服务列表,以服务名(spring.application.name)作为路径创建动态路由进行转发,从而实现动态路由功能。
-
我们可以在配置文件中,将 Route 的 uri 地址修改为以下形式。
lb://service-name
-
以上配置说明如下:
- lb:uri 的协议,表示开启 Spring Cloud Gateway 的负载均衡功能。
- service-name:服务名,Spring Cloud Gateway 会根据它获取到具体的微服务地址。
-
测试下 Spring Cloud Gateway 是如何实现动态路由的, 修改microservice-cloud-gateway-8015 中 application.yml 的配置,使用注册中心中的微服务名创建动态路由进行转发,配置如下。
server:
port: 8015
spring:
application:
name: microServiceCloudGateway #微服务名称,对外暴漏的微服务名称,十分重要
cloud:
gateway: #网关路由配置
discovery:
locator:
enabled: true #默认值为 false,即默认不开启从注册中心动态创建路由的功能,利用微服务名进行路由。启用 DiscoveryClient 网关集成
routes:
- id: provider_deptlist_route #路由 id,没有固定规则,但唯一,建议与服务名对应
uri: lb://MICROSERVICECLOUDPROVIDERDEPT #动态路由,使用服务名代替上面的具体带端口
predicates:
#以下是断言条件,必选全部符合条件
- Path=/dept/** #断言,路径匹配 注意:Path 中 P 为大写
- Method=Get #只能时 GET 请求时,才能访问
#将 microservice-cloud-provider-dept-8001 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 9527
#eureka配置,Spring cloud 自定义服务名称和 ip 地址
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
#defaultZone: http://localhost:7001/eureka/ #这个地址是 7001注册中心在 application.yml 中暴露出来额注册地址 (单机版)
defaultZone: http://eurekaserver7001.com:7001/eureka/,http://eurekaserver7002.com:7002/eureka/,http://eurekaserver7003.com:7003/eureka/ #将服务注册到 Eureka Server 集群
instance:
instance-id: microservice-cloud-gateway-8015 #自定义服务名称描述信息
prefer-ip-address: true #显示访问路径的 ip 地址
hostname: microservice-cloud-gateway
#zookeeper需要配置那些服务service被扫描,eureka则是将整个服务包注册进去了
ribbon:
eager-load:
enabled: true #关闭懒加载
# 指的是建立连接后从服务器读取到可用资源所用的时间
ReadTimeout: 6000
# 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间
ConnectTimeout: 6000
MaxAutoRetriesNextServer: 1
MaxAutoRetries: 1
# spring cloud 使用 Spring Boot actuator 监控完善信息
# Spring Boot 2.50对 actuator 监控屏蔽了大多数的节点,只暴露了 heath 节点,本段配置(*)就是为了开启所有的节点
# zuul中包含actuator依赖
management:
endpoints:
web:
exposure:
include: health,info,hystrix.stream #应包含的端点 ID 或 '' 全部,* 在yaml 文件属于关键字,所以需要加双引号
#include的值也可以改成*,但建议还是最小暴露原则,用啥开启啥
info:
env:
enabled: true #启用配置里的info开头的变量
info: #配置一些服务描述信息,监控信息页面显示,,可以判断服务是否正常
app.name: microservice-cloud-zuul-8010
company.name: cloud.zk.com
auth: zk
email: 123@qq.com
build.aetifactId: @project.artifactId@
build.version: @project.version@
#网关路径http://cloud.zk.com:8010/microservicecloudproviderdepthystrix/dept/getInfo/Hystrix/200/1
- 依次启动 Eureka 服务注册中心(集群)、服务提供者集群(microservice-cloud-provider-dept-8001/8002/8003)以及 microservice-cloud-gateway-8015。
- 在浏览器中访问“http://localhost:8015/dept/list”,结果如下图。发现数据来源于三个提供者服务
9.5 Filter 过滤器
-
通常情况下,出于安全方面的考虑,服务端提供的服务往往都会有一定的校验逻辑,例如用户登陆状态校验、签名校验等。
-
在微服务架构中,系统由多个微服务组成,所有这些服务都需要这些校验逻辑,此时我们就可以将这些校验逻辑写到 Spring Cloud Gateway 的 Filter 过滤器中。
-
Filter 的分类:Spring Cloud Gateway 提供了以下两种类型的过滤器,可以对请求和响应进行精细化控制。
过滤器类型 | 说明 |
---|---|
Pre 类型 | 这种过滤器在请求被转发到微服务之前可以对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。 |
Post 类型 | 这种过滤器在微服务对请求做出响应后可以对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。 |
- 按照作用范围划分,Spring Cloud gateway 的 Filter 可以分为 2 类:
- GatewayFilter:应用在单个路由或者一组路由上的过滤器。
- GlobalFilter:应用在所有的路由上的过滤器。
9.5.1 GatewayFilter 网关过滤器
-
GatewayFilter 是 Spring Cloud Gateway 网关中提供的一种应用在单个或一组路由上的过滤器。它可以对单个路由或者一组路由上传入的请求和传出响应进行拦截,并实现一些与业务无关的功能,比如登陆状态校验、签名校验、权限校验、日志输出、流量监控等。
-
GatewayFilter 在配置文件(例如 application.yml)中的写法与 Predicate 类似,格式如下。
spring:
cloud:
gateway:
routes:
- id: xxxx
uri: xxxx
predicates:
- Path=xxxx
filters:
- AddRequestParameter=X-Request-Id,1024 #过滤器工厂会在匹配的请求头加上一对请求头,名称为 X-Request-Id 值为 1024
- PrefixPath=/dept #在请求路径前面加上 /dept
……
- Spring Cloud Gateway 内置了多达 31 种 GatewayFilter,下表中列举了几种常用的网关过滤器及其使用示例。
路由过滤器 | 描述 | 参数 | 使用示例 |
---|---|---|---|
AddRequestHeader | 拦截传入的请求,并在请求上添加一个指定的请求头参数。 | name:需要添加的请求头参数的 key; value:需要添加的请求头参数的 value。 | – AddRequestHeader=my-request-header,1024 |
AddRequestParameter | 拦截传入的请求,并在请求上添加一个指定的请求参数。 | name:需要添加的请求参数的 key; value:需要添加的请求参数的 value。 | – AddRequestParameter=my-request-param,cloud.zk.com |
AddResponseHeader | 拦截响应,并在响应上添加一个指定的响应头参数。 | name:需要添加的响应头的 key; value:需要添加的响应头的 value。 | – AddResponseHeader=my-response-header,cloud.zk.com |
PrefixPath | 拦截传入的请求,并在请求路径增加一个指定的前缀。 | prefix:需要增加的路径前缀。 | – PrefixPath=/consumer |
PreserveHostHeader | 转发请求时,保持客户端的 Host 信息不变,然后将它传递到提供具体服务的微服务中。 | 无 | – PreserveHostHeader |
RemoveRequestHeader | 移除请求头中指定的参数。 | name:需要移除的请求头的 key。 | – RemoveRequestHeader=my-request-header |
RemoveResponseHeader | 移除响应头中指定的参数。 | name:需要移除的响应头。 | – RemoveResponseHeader=my-response-header |
RemoveRequestParameter | 移除指定的请求参数。 | name:需要移除的请求参数。 | – RemoveRequestParameter=my-request-param |
RequestSize | 配置请求体的大小,当请求体过大时,将会返回 413 Payload Too Large。 | maxSize:请求体的大小。 | – name: RequestSize args: maxSize: 5000000 |
- 来测试 GatewayFilter 的配置,在 microservice-cloud-gateway-8015 的 application.yml 中在修改成一个包含断言和过滤器动态路由,配置内容如下。
spring:
application:
name: microServiceCloudGateway #微服务名称,对外暴漏的微服务名称,十分重要
cloud:
gateway: #网关路由配置
discovery:
locator:
enabled: true #默认值为 false,即默认不开启从注册中心动态创建路由的功能,利用微服务名进行路由。启用 DiscoveryClient 网关集成
routes:
- id: provider_deptlist_route #路由 id,没有固定规则,但唯一,建议与服务名对应
uri: lb://MICROSERVICECLOUDPROVIDERDEPT #动态路由,使用服务名代替上面的具体带端口
predicates:
#以下是断言条件,必选全部符合条件
- Path=/** #断言,路径匹配 注意:Path 中 P 为大写
- Method=Get #只能时 GET 请求时,才能访问
#将 microservice-cloud-provider-dept-8001 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 9527
filters:
- PrefixPath=/dept #在请求路径上增加一个前缀 /dept
- 重启 microservice-cloud-gateway-8015,使用浏览器访问“http://localhost:8015/get/1”或,结果如下图。
9.5.2 GlobalFilter 全局过滤器
- GlobalFilter 是一种作用于所有的路由上的全局过滤器,通过它,我们可以实现一些统一化的业务功能,例如权限认证、IP 访问限制等。当某个请求被路由匹配时,那么所有的 GlobalFilter 会和该路由自身配置的 GatewayFilter 组合成一个过滤器链。
- Spring Cloud Gateway 为我们提供了多种默认的 GlobalFilter,例如与转发、路由、负载均衡等相关的全局过滤器。但在实际的项目开发中,通常我们都会自定义一些自己的 GlobalFilter 全局过滤器以满足我们自身的业务需求,而很少直接使用 Spring Cloud Config 提供这些默认的 GlobalFilter。
关于默认的全局过滤器的详细内容,请参考 Spring Cloud 官网。
- 测试下,如何自定义 GlobalFilter 全局过滤器。在 com.example.filter 包下,新建一个名为 MyGlobalFilter 全局过滤器配置类,代码如下。
package com.example.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author CNCLUKZK
* @create 2022/9/24-1:21
*/
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("进入自定义全局过滤器!");
String acc = exchange.getRequest().getQueryParams().getFirst("acc");
if (acc ==null) {
log.info("参数 acc 不能为 null!");
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
//过滤器的顺序,0 表示第一个
return 0;
}
}
-
重启 microservice-cloud-gateway-8015,使用浏览器访问“http://localhost:8015/list”或,结果如下图。 直接报400错误
-
访问“http://localhost:8015/list?acc=2”或,结果如下图。 直接报400错误
下一篇:SpringCloud-26-Zuul:路由网关介绍和使用
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123798.html