SpringCloudGateway核⼼概念和⼯作原理
Gateway 是官⽅基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的⽹关,Spring Cloud Gateway 旨在为微服务架构提供⼀种简单有效的、统⼀的 API 路由管理⽅式。
Spring Cloud Gateway 作为 Spring Cloud ⽣态系中的⽹关,其⽬标是替代 Netflix Zuul,它不仅提供统⼀的路由⽅式,并且基于 Filter 链的⽅式提供了⽹关基本的功能,例如:安全、监控/埋点和限流等。
Spring Cloud Gateway 依赖 Spring Boot 和 Spring WebFlux,基于 Netty 运⾏。它不能在传统的 servlet 容器中⼯作,也不能构建成 war 包。
在 Spring Cloud Gateway 中有如下⼏个核⼼概念需要我们了解:
1)Route
Route 是⽹关的基础元素,由 ID、⽬标 URI、断⾔、过滤器组成。当请求到达⽹关时,由 Gateway Handler Mapping 通过断⾔进⾏路由匹配(Mapping),当断⾔为真时,匹配到路由。
2)Predicate
Predicate 是  8 中提供的⼀个函数。输⼊类型是 Spring Framework ServerWebExchange。它允许开发⼈员匹配来⾃ HTTP 的请求,例如请求头或者请求参数。简单来说它就是匹配条件。
3)Filter
Filter 是 Gateway 中的过滤器,可以在请求发出前后进⾏⼀些业务上的处理。
Spring Cloud Gateway ⼯作原理
Spring Cloud Gateway 的⼯作原理跟 Zuul 的差不多,最⼤的区别就是 Gateway 的 Filter 只有 pre 和 post 两种。下⾯我们简单了解⼀下Gateway 的⼯作原理图,如图 1 所⽰。
图 1  Spring Cloud Gateway ⼯作原理
客户端向 Spring Cloud Gateway 发出请求,如果请求与⽹关程序定义的路由匹配,则该请求就会被发送到⽹关 Web 处理程序,此时处理程序运⾏特定的请求过滤器链。
过滤器之间⽤虚线分开的原因是过滤器可能会在发送代理请求的前后执⾏逻辑。所有 pre 过滤器逻辑先执⾏,然后执⾏代理请求;代理请求完成后,执⾏ post 过滤器逻辑。
Spring Cloud Gateway整合Eureka路由转发
先创建⼀个 Gateway 项⽬,然后实现了⼀个最简单的转发功能,并进⾏ Eureka 路由的整合。
创建 Gateway 项⽬
创建⼀个  Boot 的项⽬,增加  Gateway 的依赖,代码如下所⽰。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath />
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
启动类就按 Spring Boot 的⽅式即可,⽆须添加额外的注解。代码如下所⽰。
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
路由转发⽰例
下⾯来实现⼀个最简单的转发功能——基于 Path 的匹配转发功能。
Gateway 的路由配置对 yml ⽂件⽀持⽐较好,我们在 resources 下建⼀个 l 的⽂件,内容如下:
server:
port: 2001
spring:
cloud:
gateway:
routes:
- id: path_route
uri: c.biancheng
predicates:
- Path=/spring_cloud
- id: path_route2
uri: c.biancheng
predicates:
- Path=/spring_cloud/**
整合 Eureka 路由
添加 Eureka Client 的依赖,代码如下所⽰。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置基于 Eureka 的路由:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user-service/**
uri 以lb://开头(lb 代表从注册中⼼获取服务),后⾯接的就是你需要转发到的服务名称,这个服务名称必须跟 Eureka 中的对应,否则会不到服务,错误代码如下:
org.springframework.cloud.gateway.support.NotFoundException: Unable to find instance for user-service1
整合 Eureka 的默认路由
Zuul 默认会为所有服务都进⾏转发操作,我们只需要在访问路径上指定要访问的服务即可,通过这种⽅式就不⽤为每个服务都去配置转发规则,当新加了服务的时候,不⽤去配置路由规则和重启⽹关。
在 Spring Cloud Gateway 中当然也有这样的功能,通过配置即可开启,配置如下:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
开启之后我们就可以通过地址去访问服务了,格式如下:
⽹关地址/服务名称(⼤写)/**
localhost:2001/USER-SERVICE/user/get?id=1
这个⼤写的名称还是有很⼤的影响,如果我们从 Zuul 升级到 Spring Cloud Gateway 的话意味着请求地址有改变,或者重新配置每个服务的路由地址,通过源码发现可以做到兼容处理,再增加⼀个配置即可:
spring:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
配置完成之后我们就可以通过⼩写的服务名称进⾏访问了,如下所⽰:
⽹关地址/服务名称(⼩写)/**
localhost:2001/user-service/user/get?id=1
注意:开启⼩写服务名称后⼤写的服务名称就不能使⽤,两者只能选其⼀。
配置源码在 org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties 类中,代码所⽰。
@ConfigurationProperties("spring.cloud.gateway.discovery.locator")
public class DiscoveryLocatorProperties {
/**
* 服务名称⼩写配置, 默认为false
*
*/
private boolean lowerCaseServiceId = false;
}
Spring Cloud Gateway的常⽤路由断⾔⼯⼚
Gateway 内置了许多路由断⾔⼯⼚,可以通过配置的⽅式直接使⽤,也可以组合使⽤多个路由断⾔⼯⼚。接下来为⼤家介绍⼏个常⽤的路由断⾔⼯⼚类。
1)Path 路由断⾔⼯⼚
Path 路由断⾔⼯⼚接收⼀个参数,根据Path 定义好的规则来判断访问的 URI 是否匹配。
spring:
cloud:
gateway:
routes:
- id: host_route
uri: c.biancheng
predicates:
- Path=/blog/detail/{segment}
2)Query 路由断⾔⼯⼚
Query 路由断⾔⼯⼚接收两个参数,⼀个必需的参数和⼀个可选的正则表达式。
spring:
cloud:
gateway:
routes:
-
id: query_route
uri: c.biancheng
predicates:
- Query=foo, ba.
3)Method 路由断⾔⼯⼚
Method 路由断⾔⼯⼚接收⼀个参数,即要匹配的 HTTP ⽅法。
spring:
cloud:
gateway:
routes:
- id: method_route
uri: baidu
predicates:
- Method=GET
4)Header 路由断⾔⼯⼚
Header 路由断⾔⼯⼚接收两个参数,分别是请求头名称和正则表达式。
spring:
cloud:
gateway:
routes:
- id: header_route
uri:
predicates:
- Header=X-Request-Id, \d+
微服务网关和注册中心区别
如果请求中带有请求头名为 x-request-id,其值与 \d+ 正则表达式匹配(值为⼀个或多个数字),则此路由匹配。
更多路由断⾔⼯⼚的⽤法,可以参考官⽅⽂档进⾏学习。
⾃定义路由断⾔⼯⼚
⾃定义路由断⾔⼯⼚需要继承 AbstractRoutePredicateFactory 类,重写 apply ⽅法的逻辑。
在 apply ⽅法中可以通过 Request() 拿到 ServerHttpRequest 对象,从⽽可以获取到请求的参数、请求⽅式、请求头等信息。apply ⽅法的参数是⾃定义的配置类,在使⽤的时候配置参数,在 apply ⽅法中直接获取使⽤。
命名需要以 RoutePredicateFactory 结尾,⽐如 CheckAuthRoutePredicateFactory,那么在使⽤的时候 CheckAuth 就是这个路由断⾔⼯⼚的名称。代码如下所⽰。
@Component
public class CheckAuthRoutePredicateFactory
extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
public CheckAuthRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
if (Name().equals("zhangsan")) {
return true;
}
return false;
};
}
public static class Config {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
使⽤⽰例如下所⽰:
spring:
cloud:
gateway:
routes:
- id: customer_route
uri: c.biancheng
predicates:
-
name: CheckAuth
args:
name: zhangsan
Spring Cloud Gateway过滤器⼯⼚的使⽤
GatewayFilter Factory 是  Gateway 中提供的过滤器⼯⼚。 Cloud Gateway 的路由过滤器允许以某种⽅式修改传⼊的 HTTP 请求或输出的HTTP 响应,只作⽤于特定的路由。
Spring Cloud Gateway 中内置了很多过滤器⼯⼚,直接采⽤配置的⽅式使⽤即可,同时也⽀持⾃定义 GatewayFilter Factory 来实现更复杂的业务需求。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: c.biancheng
filters:
- AddRequestHeader=X-Request-Foo, Bar
接下来为⼤家介绍⼏个常⽤的过滤器⼯⼚类。
1. AddRequestHeader 过滤器⼯⼚
通过名称我们可以快速明⽩这个过滤器⼯⼚的作⽤是添加请求头。
符合规则匹配成功的请求,将添加 X-Request-Foo:bar 请求头,将其传递到后端服务中,后⽅服务可以直接获取请求头信息。代码如下所⽰。
@GetMapping("/hello")
public String hello(HttpServletRequest request) throws Exception {
return"success";
}
2. RemoveRequestHeader 过滤器⼯⼚
RemoveRequestHeader 是移除请求头的过滤器⼯⼚,可以在请求转发到后端服务之前进⾏ Header 的移除操作。
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: c.biancheng
- RemoveRequestHeader=X-Request-Foo
3. SetStatus 过滤器⼯⼚
SetStatus 过滤器⼯⼚接收单个状态,⽤于设置 Http 请求的响应码。它必须是有效的 Spring
Httpstatus(org.springframework.http.HttpStatus)。它可以是整数值 404 或枚举类型 NOT_FOUND。
spring:
cloud:
gateway:
routes:
- id: setstatusint_route
uri: c.biancheng
filters:
- SetStatus=401
4. RedirectTo过滤器⼯⼚
RedirectTo 过滤器⼯⼚⽤于重定向操作,⽐如我们需要重定向到百度。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。