Spring Cloud Gateway
1.简介
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
Spring Cloud Gateway 底层使用了高性能的通信框架Netty。
2.支持特性
2.1 特征
SpringCloud官方,对SpringCloud Gateway 特征介绍如下:
(1)基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
(2)集成 Hystrix 断路器
(3)集成 Spring Cloud DiscoveryClient
(4)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
(5)具备一些网关的高级功能:动态路由、限流、路径重写
从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。
2.2 三个术语
简单说明一下上文中的三个术语:
(1)Route(路由):网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言(Predicate)和一组过滤器(filter)定义。断言相当于判断条件,如果断言为真,则路由匹配,目标URI会被访问。
(2)Filter(过滤器):对请求和响应进行修改处理。和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。
SpringCloudGateway 内置了很多种强大的过滤工厂,能够满足各种场景的需求,可以查看官网 >;官网 filter 地址
自定义Filter接口类 | 作用域 |
---|---|
GatewayFilter | 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上 |
GlobalFilter | 全局过滤器 ,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。 |
(3)Predicate(断言):可以使用这个匹配来自HTTP请求的任何内容,这是一个 Java 8 的 Predicate,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。
断言可以匹配的项:
- ZonedDateTime:根据时间来进行匹配
- Cookie:根据cookie来进行匹配
- Header:根据请求头来进行匹配
- Host:根据请求域名来进行匹配
- Method:根据请求方法来进行匹配
- Path:根据请求路径来进行匹配
- Query:根据请求参数来进行匹配
- RemoteAddr:根据远程IP进行谓词的校验匹配
3. 处理流程
客户端(Gateway Client)向SpringCloud Gateway 发送请求,然后Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到Gateway Web Handler , Handler在通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
3.Demo项目
3.1 项目准备
- 启动Nacos Nacos 安装地址: https://nacos.io/zh-cn/docs/quick-start.html
- 创建 provider 服务项目
- 创建 open-feign 接口服务
- provirder、open-feign 参考Nacos集成OpenFegin
- 创建 nacos-gateway 网关服务
Demo git 地址: https://gitee.com/DianHaiShiYuDeMing/nacos-demo
3.2 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-demo</artifactId>
<groupId>com.example</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<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-gateway</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
</project>
3.3 启动类
package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(NacosGatewayApplication.class, args);
}
}
3.4 自定义过滤器
3.4.1 GatewayFilter
package com.example.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class DemoGatewayFilter implements GatewayFilter , Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
System.out.println("GatewayFilter 过滤器, path:"+ path+" 新增token操作" );
// 修改 request
ServerHttpRequest request = exchange.getRequest().mutate().header("x-token", "123456").build();
return chain.filter(exchange.mutate().request(request).build());
}
@Override
public int getOrder() {
return 0;
}
}
3.4.2 GlobalFilter
package com.example.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局自定义 filter
*/
@Component
public class DemoGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().toString();
System.out.println("进入了GlobalFilter全局过滤器, path:" + path + " 新增token操作");
// 修改 request
ServerHttpRequest request = exchange.getRequest().mutate().header("x-token", "123456").build();
return chain.filter(exchange.mutate().request(request).build());
}
@Override
public int getOrder() {
return 0;
}
}
3.5 appliaction.properties
server.port=8040
spring.application.name=nacos-gateway
#Nacos 配置
## 名称空间
spring.cloud.nacos.discovery.namespace=evone
## nacos 链接账号 没有设置不可以不选
spring.cloud.nacos.username=evone
# nacos 链接 密码 没有设置不可以不选
spring.cloud.nacos.password=evone123456
# spring.cloud.nacos.server-addr=192.168.104.110:8848 使用的nacos改了端口号, 默认端口 8848
spring.cloud.nacos.server-addr=192.168.104.110:16848
#GateWay 配置
## GateWay 开启从Nacos 中获取服务信息
spring.cloud.gateway.discovery.locator.enabled=true
##配置路由 也可以用java类 配置
###第一个
#spring.cloud.gateway.routes[0].id=consumer-gateway
#spring.cloud.gateway.routes[0].uri=lb://open-fegin
#spring.cloud.gateway.routes[0].predicates[0]=Path=/test/**
### 第二个
#spring.cloud.gateway.routes[1].id=
#spring.cloud.gateway.routes[1].uri=
#spring.cloud.gateway.routes[1].predicates[0]=
3.6 GatewayConfig 路由配置
package com.example.gateway.config;
import com.example.gateway.filter.DemoGatewayFilter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
/**
* 路由配置
*
* @param builder
* @return
*/
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes().route(r ->
r.path("/**")
.filters(f -> f.filter(new DemoGatewayFilter()))
.uri("lb://open-fegin")
.id("自定义id")
).build();
}
}
4.运行测试
- 启动 provider
- 启动 open-feign
- 启动 nacos-gateway
请求到了 我这个是 Hystrix 异常提示了 问题不大