概述简介
是什么
SpringCloud Gateway 使用Webflux中reactor-netty响应式编程组件,底层使用了Netty通讯框架。
能干嘛
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
微服务架构中网关的位置
为什么选择Gateway?
Gateway基于异步非阻塞模型上进行开发,性能不错,且Zuul2在2020年就停止维护了。多方面综合考虑Gateway是很理想的网关选择。
Gateway的特性
- 基于Spring5、Project Reactor和Spring Boot2.0进行构建。
- 动态路由:能够匹配任何请求属性
- 可以对路由指定断言(predicate)和过滤器(filter)
- 集成Hystrix的断路器功能
- 集成Spring Cloud服务发现功能
- 易于编写的Predicate和Filter
- 请求限流功能
- 支持路径重写
三大核心概念
路由 Route
路由是构建网关的基本模块,它由ID、目标URI、一系列的断言和过滤器组成,如果断言为true则匹配该路由。
断言 Predicate
开发人员可以匹配HTTP请求中的所有内容,如果请求与断言相匹配则进行路由
过滤 Filter
Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
Gateway工作流程
入门配置
- 建module
- 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
- 写properties / yaml
server.port=9527
spring.application.name=cloud-gateway
eureka.instance.hostname=cloud-gateway-service
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka/
# 路由的ID,唯一
spring.cloud.gateway.routes[0].id=payment_routh
# uri
spring.cloud.gateway.routes[0].uri=http://localhost:8001
# 断言配置
spring.cloud.gateway.routes[0].predicates[0]=Path=/payment/get/**
spring.cloud.gateway.routes[1].id=payment_routh1
spring.cloud.gateway.routes[1].uri=http://localhost:8001
spring.cloud.gateway.routes[1].predicates[0]=Path=/payment/lb/**
- 启动类
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayMain9527.class, args);
}
}
- 使用配置类实现路由匹配与转发(代替properties中的路由匹配与转发)
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_1", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
@Bean
public RouteLocator routes1(RouteLocatorBuilder routeLocatorBuilder){
...
}
}
通过微服务名实现动态路由
在配置文件里进行额外的配置:
# 路由的ID,唯一
spring.cloud.gateway.routes[0].id=payment_routh
# uri
spring.cloud.gateway.routes[0].uri=lb://cloud-payment-service
# 断言配置
spring.cloud.gateway.routes[0].predicates[0]=Path=/payment/get/\(这个斜杠是为了转义,实际上是不存在的)**
spring.cloud.gateway.routes[1].id=payment_routh1
spring.cloud.gateway.routes[1].uri=lb://cloud-payment-service
spring.cloud.gateway.routes[1].predicates[0]=Path=/payment/lb/\(这个斜杠是为了转义,实际上是不存在的)**
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
spring.cloud.gateway.discovery.locator.enabled=true
Predicate的使用
常用的predicate
- after
//propertites
spring.cloud.gateway.routes[0].predicates[1]=After=2022-06-13T22:59:07.890+08:00[Asia/Shanghai]
//通过ZonedDateTime得到时间串
ZonedDateTime zbj = ZonedDateTime.now();
- before:
spring.cloud.gateway.routes[0].predicates[1]=Before=2022-06-13T23:59:07.890+08:00[Asia/Shanghai]
- between:
spring.cloud.gateway.routes[0].predicates[1]=Between=2022-06-13T22:59:07.890+08:00[Asia/Shanghai],2022-06-13T23:59:07.890+08:00[Asia/Shanghai]
- Cookie:
spring.cloud.gateway.routes[0].predicates[1]=Cookie=chocolate, ch.p
,chocolate
是Cookie的名字,ch.p
是正则表达式。 - Header:
spring.cloud.gateway.routes[0].predicates[1]=Header=X-Request-Id, \d+
,请求头要有X-Request-Id属性并且值为整数的正则表达式。 - Host:
spring.cloud.gateway.routes[0].predicates[1]=Host=**.baidu.com
- Method:
spring.cloud.gateway.routes[0].predicates[1]=Method=Get
- Query:
spring.cloud.gateway.routes[0].predicates[1]=Query=username,z2h
Filter的使用
有两类,GatewayFilter和GlobalFilter
-
GatewayFilter:https://cloud.spring.io/spring-cloud-gateway/reference/html/#gatewayfilter-factories
举个例子,在配置类中设置:spring.cloud.gateway.routes[0].filters[0]=AddRequestParameter=X-Request-Id,1024
,则需要加上额外的请求头。
-
GlobalFilter:https://cloud.spring.io/spring-cloud-gateway/reference/html/#global-filters
自定义过滤器
需要实现两个接口:GloablFilter
和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,非法用户");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}