一、Gateway概述
1、Gateway是什么
Cloud在1.x版本中采用的都是Zuul网关,但在2.x版本中,zuul升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,那就是 SpringCloud Gatewaty。
- Gateway 是在 Spring 生态系统之上构建的 API 网关服务,基于 Spring 5、Spring Boot 2 和 Project Reactor 等技术。它提供了一种简单且有效的方式来对 API 进行路由,并提供了一些强大的过滤器功能(熔断、限流、重试等)。
- Gateway 的底层是基于 WebFlux 框架实现的,而webFlux底层使用netty通信(NIO)。
- Gateway 使用非阻塞 API,支持 WebSocket 且与 Spring 紧密集成。
官网:https://spring.io/projects/spring-cloud-gateway
2、Gateway能干什么
反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
3、Gateway具有的特征
- 基于Spring Frameword5 ,Project Reactor 和 SpringBoot 2.0进行构建;
- 动态路由:能够匹配任何请求属性
- 可以对路由指定Predicate(断言)和Filter(过滤器)
- 集成Hystrix的断路器功能;
- 集成Spring Cloud的服务发现功能
- 易于编写的Predicate(断言)和Filter(过滤器)
- 请求限流功能;
- 支持路径重写
4、Gateway与zuul的区别
在SpringCloud Finchley 正式版之前(现在H版),SpringCloud推荐的网关是Netflix提供的zuul。
- Zuul1.x 是一个基于阻塞 I/O的API网关
- Zuul1.x 基于Servlet2.5使用阻塞架构它不支持任何长连接 (如WebSocket)Zuul的设计模式和Nginx较像,每次I/O操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul用java实现,而JVM本身会有第一次加载较慢的情况,使得Zuul的性能相对较差。
- Zuul 2.x理念更加先进,像基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。Zuul2.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紧密集成拥有更好的开发体验。
二、Gateway的三大核心概念
Route 路由: 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,就是根据某些规则,将请求发送到指定服务上。
- Predicate 断言:参考的是Java8的java.util.function.Predicate,使开发人员能够匹配 HTTP 请求中的所有内容(请求头/请求参数),如果请求与断言相匹配则进行路由。
- Filter 过滤: 实现的过滤器可以在请求被路由前或者之后,对请求进行修改。
三、Gateway的工作流程
- 客户端向 Gateway 发出请求
- 在 Gateway Handler Mapping 中找到与请求匹配的路由,将其发送到 Gateway Handler。
- Handler 再通过指定的过滤器链,然后将请求发送到实际的服务执行业务逻辑,最后返回。
过滤器链之间用虚线分开,是因为在发送请求之前或之后执行一些其他的业务逻辑:
- 之前:参数校验、权限校验、流量监控、日志输出、协议转换等。
-
四、Gateway入门案例
1、Gateway搭建
创建工程 cloud-gateway-gateway9527
写pom:webflux和web模块冲突,记得删除
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
写yml ```yaml server: port: 9527
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true # 开启从注册中心取服务名,动态创建路由的功能 routes:
- id: payment_routh # 路由的 ID,没有固定规则但要求唯一
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/lb/**
eureka: instance: hostname: cloud-gateway-service client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://eureka7001.com:7001/eureka
4. 写主程序
```java
@EnableEurekaClient
@SpringBootApplication
public class GateWayApplication9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication9527.class, args);
}
}
- 测试,启动7001、8001、9527,访问http://localhost:9527/payment/get/1
2、硬编码配置
GateWay的网关配置,除了支持配置文件,还支持硬编码方式,使用硬编码配置GateWay:
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_moke",r->r.path("/guonei")
.uri("http://news.baidu.com/"));
return routes.build();
}
}
3、动态路由 routes
4、断言 predicates
- After:可以指定,只有在指定时间后,才可以路由到指定微服务,在指定的时间之前访问,都会报404。
- before:与after类似,他说在指定时间之前的才可以访问
- between:需要指定两个时间,在他们之间的时间才可以访问
- cookie:只有包含某些指定cookie(key,value),的请求才可以路由
- Header:只有包含指定请求头的请求,才可以路由
- Host:只有指定主机的才可以访问
- Method:只有指定请求才可以路由,比如get请求…
- Path:只有访问指定路径,才进行路由,我们已经用过了
- Query:必须带有请求参数才可以访问
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心取服务名,动态创建路由的功能
routes:
- id: payment_routh # 路由的 ID,没有固定规则但要求唯一
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_routh2
uri: http://localhost:8001
predicates:
predicates:
- After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai] # 时间生效
- Before=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]
- Between=2017-01-20T17:42:47.789-07:00[Asia/Shanghai], 2017-01-21T17:42:47.789-07:00[America/Denver]
- Cookie=chocolate, ch.p # cookie命名的请求,其值与常规表达式相匹配
- Header=X-Request-Id, \d+ # header包含指定元素,且value是数字
- Host=**.somehost.org,**.anotherhost.org # 指定主机才能访问
- Method=GET,POST
- Path=/payment/get/**,Path=/payment/lb/**
5、过滤器 Filter
- 路由过滤器可用于修改进入的Http请求和返回的Http响应,路由过滤器只能过滤指定路由进行使用。
Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生,分为单一过滤器、全局过滤器,过滤器的类型可以在网关 (spring.io)查看。
1、单一过滤器
spring: cloud: gateway: routes: - id: add_request_header_route uri: https://example.org filters: - AddRequestHeader=X-Request-red, blue
2、全局过滤器
Spring提供了很多全局过滤器,但是我们一般使用自定义的全局过滤器足够。
自定义全局过滤器
@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("username"); if(StringUtils.isEmpty(username)){ log.info("*****用户名为Null 非法用户,(┬_┬)"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//给人家一个回应 return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
加入到IOC容器
@Bean public GlobalFilter customFilter() { return new CustomGlobalFilter(); }