SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则应用了高性能的 Reactor 模式通信框架 Netty。
Cloud 全家桶中有个很重要的组件就是网关,在 1.x 版本中都是采纳的 Zuul 网关;
但在 2.x 版本中,zuul 的降级始终跳票,SpringCloud 最初本人研发了一个网关代替 Zuul,那就是 SpringCloud Gateway—句话:gateway 是原 zuul1.x 版的代替
Gateway 是在 Spring 生态系统之上构建的 API 网关服务,基于 Spring 5,Spring Boot 2 和 Project Reactor 等技术。
Gateway 旨在提供一种简略而无效的形式来对 API 进行路由,以及提供一些弱小的过滤器性能,例如: 熔断、限流、重试等。
SpringCloud Gateway 是 Spring Cloud 的一个全新我的项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供—种简略无效的对立的 API 路由治理形式。
SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,指标是代替 Zuul,在 Spring Cloud 2.0 以上版本中,没有对新版本的 Zul 2.0 以上最新高性能版本进行集成,依然还是应用的 Zuul 1.x 非 Reactor 模式的老版本。而为了晋升网关的性能,SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则应用了高性能的 Reactor 模式通信框架 Netty。
Spring Cloud Gateway 的指标提供对立的路由形式且基于 Filter 链的形式提供了网关根本的性能,例如: 平安,监控 / 指标,和限流。
3、为什么抉择 Gateway?
Gateway 的个性
基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0 进行构建;
动静路由:可能匹配任何申请属性;
能够对路由指定 Predicate (断言)和 Filter(过滤器);
集成 Hystrix 的断路器性能;
集成 Spring Cloud 服务发现性能;
易于编写的 Predicate (断言)和 Filter (过滤器);
申请限流性能;
反对门路重写。
SpringCloud Gateway 与 Zuul 的区别
在 SpringCloud Finchley 正式版之前,Spring Cloud 举荐的网关是 Netflix 提供的 Zuul。
Zuul 1.x,是一个基于阻塞 I / O 的 API Gateway。
Zuul 1.x 基于 Servlet 2.5 应用阻塞架构它不反对任何长连贯 (如 WebSocket)Zuul 的设计模式和 Nginx 较像,每次 I /О操作都是从工作线程中抉择一个执行,申请线程被阻塞到工作线程实现,然而差异是 Nginx 用 C ++ 实现,Zuul 用 Java 实现,而 JVM 自身会有第 - 次加载较慢的状况,使得 Zuul 的性能绝对较差。
Zuul 2.x 理念更先进,想基于 Netty 非阻塞和反对长连贯,但 SpringCloud 目前还没有整合。Zuul .x 的性能较 Zuul 1.x 有较大晋升。在性能方面,依据官网提供的基准测试,Spring Cloud Gateway 的 RPS(每秒申请数) 是 Zuul 的 1.6 倍。
Spring Cloud Gateway 建设在 Spring Framework 5、Project Reactor 和 Spring Boot2 之上,应用非阻塞 API。
Spring Cloud Gateway 还反对 WebSocket,并且与 Spring 严密集成领有更好的开发体验
http://www.bilibili.com/media…
http://www.bilibili.com/media…
http://www.bilibili.com/media…
http://www.bilibili.com/media…
http://www.bilibili.com/media…
http://www.thinksaas.cn/user/…
二、三大外围概念
1、三大概念
Route(路由):路由是构建网关的根本模块, 它由 ID, 指标 URI, 一系列的断言和过滤器组成, 如断言为 true 则匹配该路由;
Predicate(断言):参考的是 Java8 的 java.util.function.Predicate,开发人员能够匹配 HTTP 申请中的所有内容(例如申请头或申请参数), 如果申请与断言相匹配则进行路由;
Filter(过滤):指的是 Spring 框架中 GatewayFilter 的实例, 应用过滤器, 能够在申请被路由前或者之后对申请进行批改。
2、Gateway 的工作流程
客户端向 Spring Cloud Gateway 发出请求。而后在 Gateway Handler Mapping 中找到与申请相匹配的路由,将其发送到 GatewayWeb Handler。
Handler 再通过指定的过滤器链来将申请发送到咱们理论的服务执行业务逻辑,而后返回。
过滤器之间用虚线离开是因为过滤器可能会在发送代理申请之前 (“pre”) 或之后 (“post”)执行业务逻辑。
三、Gateway 配置
1、环境
新建模块:cloud-gateway-gateway9527
pom:
<?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>cloud2021</artifactId>
<groupId>com.atguigu</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-gateway-gateway9527</artifactId>
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入本人定义的 api 通用包,能够应用 Payment 领取 Entity -->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 个别根底配置类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
复制代码
yaml:
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者 provider 注册进 eureka 服务列表内
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
复制代码
主启动类:
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527
{
public static void main(String[] args) {SpringApplication.run(GateWayMain9527.class, args);
}
}
复制代码
业务类:无
2、gateway 配置
为了保障能够路由跳转,加上如下代码:
server:
port: 9527
spring:
application:
name: cloud-gateway
############################# 新增网关配置 ###########################
cloud:
gateway:
routes:
- id: payment_routh #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
#uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,门路相匹配的进行路由
- id: payment_routh2 #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
#uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,门路相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者 provider 注册进 eureka 服务列表内
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
复制代码
启动测试。
这回拜访 http://localhost:9527/payment… 就能够了。
3、编码方式配置
下面采纳 yaml 形式配置,当初能够应用编码方式配置。
@Configuration
public class GateWayConfig
{
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
{RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_atguigu",
r -> r.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();}
}
复制代码
间接拜访 http://localhost:9527/guonei
四、依据微服务名实现动静路由
这里要模仿应用 gateway 的形式实现动静路由,而不是 ribbon 了。
9527 模块的 yaml 文件批改成这样:
server:
port: 9527
spring:
application:
name: cloud-gateway
新增网关配置
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册核心动态创建路由的性能,利用微服务名进行路由
routes:
- id: payment_routh #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,门路相匹配的进行路由
- id: payment_routh2 #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,门路相匹配的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者 provider 注册进 eureka 服务列表内
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
复制代码
启动测试:localhost:9527/payment/lb,发现的确实现了轮询操作
五、Predicate 的应用
9527 启动后,发现后盾呈现了这些
进入 gateway 官网(下面有),发现一共有 11 种 Predicate
Predicate 是什么
Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础架构的一部分。
Spring Cloud Gateway 包含许多内置的 Route Predicate 工厂。所有这些 Predicate 都与 HTTP 申请的不同属性匹配。多个 Route Predicate 工厂能够进行组合。
Spring Cloud Gateway 创立 Route 对象时,应用 RoutePredicateFactory 创立 Predicate 对象,Predicate 对象能够赋值给 Route。Spring Cloud Gateway 蕴含许多内置的 Route Predicate Factories。
所有这些谓词都匹配 HTTP 申请的不同属性。多种谓词工厂能够组合,并通过逻辑 and。
After Route Predicate Factory 的应用
依照官网的说法:
在 yaml 文件底下加上一行即可,然而要批改成中国工夫:
测试,发现这样能够获取到下面格局的工夫:
public class T2 {
public static void main(String[] args) {ZonedDateTime zbj = ZonedDateTime.now();
System.out.println(zbj);
}
}
// 输入
//2021-11-23T10:44:35.485+08:00[Asia/Shanghai]
复制代码
那么批改一下:
routes:
- id: payment_routh #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/**
- After=2021-11-23T10:44:35.485+08:00[Asia/Shanghai]
复制代码
而后这样就代表下面这个路由只有在某某工夫之后能力应用,当初把下面 after 的工夫批改一下,再启动测试发现报错了,阐明的确失效了,这种有点相似秒杀场景、或者我的项目定时上线都能够采纳这种形式。
Cookie Route Predicate 的应用
就是要求带不带 cookie,或者带哪种 cookie。
Cookie Route Predicate 须要两个参数,一个是 cookie name,一个是正则表达式。路由的规定会通过正则表达式与 cookie 进行匹配。
-
id: payment_routh2 #payment_route #路由的 ID,没有固定规定但要求惟一,倡议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:- Path=/payment/lb/** # 断言,门路相匹配的进行路由
- After=2021-11-23T10:44:35.485+08:00[Asia/Shanghai]
- Cookie=username, James
复制代码
这里采纳 curl 的形式发送申请:
其余的依照官网去写即可。
六、Filter 的应用
路由过滤器可用于批改进入的 HTTP 申请和返回的 HTTP 响应,路由过滤器只能指定路由进行应用。Spring Cloud Gateway 内置了多种路由过滤器,他们都由 GatewayFilter 的工厂类来产生。
过滤器个别只有两种:
GatewayFilter
GlobalFilter
自定义全局过滤器
过滤器太多了,要学也很麻烦,这里实现自定义过滤器,举个例子同时也更加通用,需要的话本人配即可:
创立个包 filter,而后创立 filter 的类,须要实现两个接口:GlobalFilter、Ordered:
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{log.info("***********come in MyLogGateWayFilter:"+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(uname == null)
{log.info("******* 用户名为 null,非法用户,o(╥﹏╥)o");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder()
{return 0;}
}