Gateway 介绍
SpringCloud Gateway是spring官方基于Spring 5.0、Spring Boot2.0和Project Reactor等技术开发的网关,旨在为微服务架构提供简单、有效和统一的API路由管理方式.
SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty.
SpringCloud Gateway不仅提供统一的路由方式,并且还基于Filer链的方式提供了网关基本的功能,例如:鉴权、监控/指标、流量控制、熔断限流等.
Gateway核心
Route(路由): 路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配
Predicate(断言): 参考的是java8的java.util.function.Predicate,开发人员可以匹配Http请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
Filter(过滤器): 一个标准的Spring webFilter。SpringCloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。使用过滤器,可以在请求被路由前或者之后对请求进行修改
第一步 在父工程(pom.xml)
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
<log4j-slf4j.version>2.17.0</log4j-slf4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springcloud alibaba依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
第二步 在网关子工程(pom.xml)中添加网关依赖和Nacos客户端依赖
<!-- 别忘记继承父工程 -->
<parent>
<groupId>org.lanqiao</groupId>
<artifactId>lanqiao-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!-- 添加网关依赖 -->
<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>
第三步 在启动类上添加注解@EnableDiscoveryClient (可选)
//注册发现客户端开关(依赖中自动开启此注解)
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderXxxxxxApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderXxxxxxApplication.class, args);
}
}
第四步 在网关子工程 application.yml 中添加nacos 注册发现地址
server:
port: 10000
spring:
application:
name: lanqiao-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
spring.cloud.nacos.discovery.server-addr :nacos注册中心的地址和进程端口
spring.application.name :微服务的名字,要具有唯一性
第五步 在网关工程 application.yml 中添加路由
server:
port: 10000
spring:
application:
name: lanqiao-gateway
cloud:
gateway:
routes:
- id: lanqiao-gateway
uri: lb://lanqiao-passenger
predicates:
## 当请求的路径为api/passenger开头的时,负载均衡到lanqiao-passenger微服务
- Path=/api/passenger/**
filters:
## StripPrefix=1就代表截取路径的个数为1,比如前端过来请求/api/passenger/view,匹配成功后,路由到后端的请求路径就会变成http://localhost:20000/passenger/view,去掉api前缀路径。
- StripPrefix=1
gateWay的主要功能之一是转发请求,转发规则的定义主要包含三个部分
Route(路由) 路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。
Predicate(谓语、断言) 路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式
Filter(过滤器) 过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容
通过网关访问微服务
http://localhost:10000/api/passenger/hello
如果访问失败,可跨过网关直接访问微服务接口,测试微服务接口是否正常,然后排查是否是网关问题
如果访问失败,网关配置不存在问题的情况下,尝试把 lb://lanqiao-passenger 换成http://localhost:20000
断言(Predicate)工厂介绍
Spring Cloud Gateway包括许多内置的路由谓词工厂。所有这些谓词都与HTTP请求的不同属性相匹配。你可以用逻辑 and 语句组合多个路由谓词工厂。
官网:https://springdoc.cn/spring-cloud-gateway/#gateway-request-predicates-factories
过滤器 filter介绍
Gateway提供了基于路由的局部过滤器和全局性的过滤器
路由过滤器:
路由(Route)过滤器(Filter)允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应。路由过滤器的范围是一个特定的路由。Spring Cloud Gateway 包括许多内置的 GatewayFilter 工厂。下面列举了几个常用的过滤器案例。
AddRequestHeader:
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
这个列表将 X-Request-red:blue header添加到所有匹配请求的下游请求的header信息中。
PrefixPath:
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
这就把 /mypath 作为所有匹配请求的路径的前缀。因此,一个到 /hello 的请求会被发送到 /mypath/hello。
RewritePath:
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- RewritePath=/red/?(?<segment>.*), /$\{segment}
对于请求路径为 /red/blue 的情况,在进行下游请求之前将路径设置为 /blue。注意,由于YAML的规范,$ 应该被替换成 $\。
StripPrefix:
StripPrefix GatewayFilter 工厂需要一个参数,即 parts。parts 参数表示在向下游发送请求之前要从路径中剥离的部分的数量。下面的列表配置了一个 StripPrefix GatewayFilter。
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
当通过网关向 /name/blue/red 发出请求时,向 nameservice 发出的请求看起来像 nameservice/red。
全局 Filter
//在filter 包下 建立自定义过滤器类
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
当一个请求与路由匹配时,filter web handler将 GlobalFilter 的所有实例和 GatewayFilter 的所有路由特定实例添加到一个过滤链中。这个组合的过滤链由 org.springframework.core.Ordered 接口进行排序,你可以通过实现 getOrder() 方法来设置这个接口。
由于 Spring Cloud Gateway 区分了过滤器逻辑执行的 “pre” 和 “post” 阶段(见如何工作),优先级最高的过滤器在 “pre” 阶段是第一个,在 “post” 阶段是最后一个。
跨域Cors配置
gateway提供了对某个路由的跨域配置,也提供了全局的跨域配置,相比而言全局的跨域配置更一劳永逸。
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowedHeaders: '*'
maxAge: 30
maxAge属性:配置预检请求的有效时间, 单位是“秒”,表示:在多长时间内,不需要发出第二次预检请求
全配置案例
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: a
uri: lb://cloud-service-a
predicates:
- Path=/a/**
filters:
- StripPrefix=1 # 转发时,去掉一层前缀 zeus
- id: b
uri: lb://cloud-service-b
predicates:
- Path=/b/**
filters:
- StripPrefix=1 # 转发时,去掉一层前缀 apollo
globalcors:
cors-configurations:
'[/**]':
# 允许携带认证信息
allowCredentials: false
# 允许跨域的源(网站域名/ip),设置*为全部
allowedOrigins: "*"
# 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
allowedMethods:
- GET
- PUT
- POST
- DELETE
- OPTIONS
# 允许跨域请求里的head字段,设置*为全部
allowedHeaders: "*"
#解决双重跨域 RETAIN_FIRST RETAIN_LAST RETAIN_UNIQUE
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST
add-to-simple-url-handler-mapping: true
# 如果没有匹配到路由依然能够跨域
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 10000
logging:
level:
org:
springframework:
cloud:
gateway: debug
lanqiao:
gateway:
filter: debug
my:
token:
whiteURIS:
- /login
- /register
- /logout