本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断,限流,重试等
——概念
- Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架,异步非阻塞。
- 应用场景:反向代理、鉴权、流量控制、熔断、日志监控
- 与Zuul的区别:
核心概念
- 动态路由:能够匹配任何请求属性,是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
- 断言:参考的是JAVA8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容,如果请求与断言相匹配则进行路由
- 过滤:指的是Spring框架中的GatewayFilter的实例,使用过滤器,可以在请求被路由前或者后对请求进行修改
- 核心逻辑:路由转发+执行过滤链
——实操
- pom
<!-- gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh # 路由的id,没有固定的规则但要求统一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates: # 断言
- Path=/payment/get/** # 指定的路径才可生效
# - After=2020-09-15T15:53:47.026+08:00[Asia/Shanghai] # 在此时间之后生效
# - Before=2020-09-15T15:53:47.026+08:00[Asia/Shanghai] # 在此时间之前生效
# - Between=2020-09-15T15:53:47.026+08:00[Asia/Shanghai],2020-09-15T16:53:47.026+08:00[Asia/Shanghai] # 在此时间之间生效
# - Cookie=username,xlj # 只有cookie包含username,并且value为xlj才生效
# - Header=X-Request-Id,\d+ # 包含指定请求头,value为数字
# - Host=**.baidu.com # 指定主机才可访问
# - Method=GET # 请求方法为GET才生效
- id: payment_routh2 # 路由的id,没有固定的规则但要求统一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的 路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/lb/** # 断言,路径相对应的进行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
fetch-registry: true
# true将服务注册到eureka
register-with-eureka: true
# 集群Eureka
defaultZone: http://eureka7001:7001/eureka,http://eureka7002:7002/eureka
# 单机版Eureka
# defaultZone: http://localhost:7001/eureka
路由配置
- yml文件配置
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh # 路由的id,没有固定的规则但要求统一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相对应的进行路由
- id: payment_routh2 # 路由的id,没有固定的规则但要求统一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径相对应的进行路由
- 配置类
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 访问http://localhost:9527/guonei跳转到http://news.baidu.com/guonei
routes.route("path_route_xlj", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
- 通过微服务名实现动态路由
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh # 路由的id,没有固定的规则但要求统一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/get/** # 断言,路径相对应的进行路由
- id: payment_routh2 # 路由的id,没有固定的规则但要求统一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的 路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/lb/** # 断言,路径相对应的进行路由
断言
predicates: # 断言
- Path=/payment/get/** # 指定的路径才可生效
- After=2020-09-15T15:53:47.026+08:00[Asia/Shanghai] # 在此时间之后生效
- Before=2020-09-15T15:53:47.026+08:00[Asia/Shanghai] # 在此时间之前生效
- Between=2020-09-15T15:53:47.026+08:00[Asia/Shanghai],2020-09-15T16:53:47.026+08:00[Asia/Shanghai] # 在此时间之间生效
- Cookie=username,xlj # 只有cookie包含username,并且value为xlj才生效
- Header=X-Request-Id,\d+ # 包含指定请求头,value为数字
- Host=**.baidu.com # 指定主机才可访问
- Method=GET # 请求方法为GET才生效
自定义配置过滤器
public class LogGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*****come in LogGatewayFilter"+ new Date());
String username = exchange.getRequest().getQueryParams().getFirst("username");
if (StringUtils.isEmpty(username)){
log.info("***用户名为空,非法进入");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}