简介
SpringCloud Gateway是SpringCloud的一个全新项目,基于Spring5+springboot2+project Reactor等技术开发的网关,它旨在为微服务架构提供一中简单有效的统一的Api路由管理方式,且基于Filter链的方式提供了网关基本的功能,如安全,监控,指标,限流。
Spring Cloud Gateway使用的webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
GateWay具有如下特性:
- 基于Spring5+springboot2+project Reactor等技术构建。
- 可以对路由指定Predicate(断言)和filter(过滤器)。
- 集成Hystrix的断路器功能。
- 集成SpringCloud服务发现功能。
- 易于编写的Predicate(断言)和filter(过滤器);
- 请求限流功能。
- 支持路径重写。
三大核心概念
路由(Route)是构建网关的基本模块,它由ID,目标URI,一系列断言和过滤器组成,如果断言为true则匹配该路由。
断言(Predicate),开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数,如果请求与断言相匹配则进行路由
过滤(Filter),指的是Spring框架中的GatewayFilter的实例,使用过滤器,可以在请求被路由前或者后对请求进行修改
官网截图:
核心逻辑:路由转发+执行过滤器链
Gateway环境搭建
yml配置方式
pom依赖:需要移除springboot的web场景启动器,否则会报错,无法启动
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置文件yml,在配置文件中配置了网关
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
uri: http://localhost:8001
predicates:
- Path=/payment/get/**
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/create
eureka:
client:
#是否将自己注册到Eureka Server 默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true,单节点无所谓,集群必须设置true才能配合ribbon做负载均衡
fetch-registry: true
service-url:
#设置eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://localhost:7001/eureka
instance:
hostname: cloud-gateway-service
然后我们通过9527端口就可以访问服务了:
编码方式配置
新写一个Gateway配置类:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_wj",r->{
//意思是访问localhost:9527/guonei,将会转发到http://news.baidu.com/guonei
return r.path("/guonei").uri("http://news.baidu.com/guonei");
}).build();
return routes.build();
}
}
我们在浏览器输入localhost:9527/guonei并访问,观察效果:
Gateway实现动态路由
yml配置
需要注意的是:uri的协议为lb,表示启用Gateway的负载均衡功能.
lb://serverName是Spring cloud Gateway在微服务中自动为我们创建的负载均衡uri
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/get/**
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/create
discovery:
locator:
#开启从注册中心动态创建路由的功能,利用微服务名进行路由
enabled: true
常用的断言
当我们启动Gateway服务时,发现控制台打印了一串Predicate
官方文档有详细说明:https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gateway-request-predicates-factories
这里不做过多介绍。
filter
filter分为两种,一个是GatewayFilter,一种是GlobalFilter。
GatewayFilter
没啥好说的,官网写的很清楚。https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories
举例:
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/get/**
#- After=2020-09-06T21:57:48.289+08:00[Asia/Shanghai]
filters:
#过滤器工厂会在匹配的请求头上加上一对请求头,名称为X-Request-red值是blue
- AddRequestHeader=X-Request-red, blue
自定义全局GlobalFilter:
需要实现两个接口,GlobalFilter和Ordered。
@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(StringUtils.isBlank(name)){
log.info("非法用户");
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
运行效果: