SpringCloud之网关组件Gateway学习
GateWay简介
Spring Cloud Gateway是Spring Cloud的⼀个全新项目,目标是取代Netflix Zuul,它基于Spring5.0+SpringBoot2.0+WebFlux(基于高性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官方测试,Gateway是Zuul的1.6倍,旨在为微服务架构提供种简单有效的统⼀的API路由管理方式。Spring Cloud Gateway不仅提供统的路由方式(反向代理)并且基于 Filter(定义过滤器对请求过滤,完成⼀些功能) 链的式提供了网关基本的功能,例如:鉴权、
流量控制、熔断、路径重写、日志监控等。
Gateway相关概念
Gateway使用
在项目中引入Gateway的依赖,这里要注意的是Gateway不支持Spring boot web包,所以需要排除掉spring-boot-starter-web
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
在微服务系统中,如果没有引入网关组件,用户的请求是直接请求到具体的服务的,而引入网关后,用户的请求会被网关组件处理,然后由网关组件将请求转发给具体的服务实例进行处理。网关组件也是一种服务,也需要被注册到Nacos等注册中心中。引入网关后的架构图如下所示:
Gateway服务配置,这一部分配置和其它的服务没有区别,是和Nacos注册中心集成的配置
server:
port: 10010 #网关端口
spring:
application:
name: gatewayservice
cloud:
nacos:
server-addr: localhost:8848
discovery:
group: testgroup1
namespace: 8ff552f0-0212-43b2-8ea0-e4c2aa359084
cluster-name: HZ
GateWay本身的配置如下:
spring:
cloud:
gateway: #路由匹配是从前往后,依次匹配的
routes: #网关路由配置
- id: providerservice #路由id,需要唯一
uri: lb://providerservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,其实就是判断请求是否符合路由规则的条件
- Path=/user/** #路由匹配 只要是以/user开头的请求就会匹配到,P需要大写,不然会报错
- id: consumerservice
uri: lb://consumerservice
predicates:
- Path=/consumer/**
然后在浏览器输入 http://localhost:10010/consumer/1,就可以访问到consumerservice服务了,这时因为GateWay服务将我们的请求根据配置的路由规则路由到了consumerservice。
路由断言工厂
路由断言工厂的作用是读取用户定义的断言条件,对请求作出判断。
我们上面的配置中的断言规则 Path=/user/** 只是字符串, 这些字符串会被Spring中的org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory处理的,类似的PredicateFactory在GateWay中还有很多。
名称 | 说明 |
---|---|
After | 某个时间之后的请求 |
Before | 某个时间之前的请求 |
Between | 某两个时间之间的请求 |
Cookie | 请求必须包含某些cookie |
Header | 请求必须包含某些Header |
Host | 请求必须是访问某个host(域名) |
Method | 请求必须是指定方式 |
Path | 请求路径必须符合指定规则 |
Query | 请求参数必须包含指定参数 |
RemoteAddr | 请求的ip必须是指定范围 |
Weight | 权重处理 |
上面这些路由断言工厂的具体使用,可以参考官方的路由断言工厂示例
过滤器
GateWay Filter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理。
Spring提供了31种不同的路由过滤器工厂,具体的使用可以参考官方的:
过滤器工厂官方示例
使用过滤器给请求添加一个请求头:
cloud:
gateway: #路由匹配是从前往后,依次匹配的
routes: #网关路由配置
- id: providerservice #路由id,需要唯一
uri: lb://providerservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,其实就是判断请求是否符合路由规则的条件
- Path=/user/** #路由匹配 只要是以/user开头的请求就会匹配到
- id: consumerservice
uri: lb://consumerservice
predicates:
- Path=/consumer/**
filters: #局部过滤器,只对某个服务起作用
- AddRequestHeader=truth,This is a headr #添加请求头
通过@RequestHeader注解来获取请求头的值
在控制台输出了获取到的请求头
如果想要过滤器对所有的路由都生效,可以把过滤器工厂写到default下
server:
port: 10010 #网关端口
spring:
application:
name: gatewayservice
cloud:
nacos:
server-addr: localhost:8848
discovery:
group: testgroup1
namespace: 8ff552f0-0212-43b2-8ea0-e4c2aa359084
cluster-name: HZ
gateway: #路由匹配是从前往后,依次匹配的
routes: #网关路由配置
- id: providerservice #路由id,需要唯一
uri: lb://providerservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,其实就是判断请求是否符合路由规则的条件
- Path=/user/** #路由匹配 只要是以/user开头的请求就会匹配到
- id: consumerservice
uri: lb://consumerservice
predicates:
- Path=/consumer/**
filters:
- AddRequestHeader=truth,This is a headr #添加请求头
default-filters:
- AddRequestHeader=truth,This is a headr1
前面提到的两种过滤器的过滤规则都是固定的,是框架给我们提供的;如果想要自定义过滤规则,则需要用到全局过滤器Global Filter。GateWay提供了GlobalFilter接口,只要我们实现这个接口就可以实现自定义的过滤器。重点是如何让过滤器链继续向下执行或者阻止过滤器链向下执行。下面是一个简单的全局过滤器示例:
/**
* @author DELL
* @version 1.0
* @description
* @date 2024/3/13 22:38:05
*/
@Order(value = 1) #指定过滤器的执行顺序,值越小越先执行
public class MyGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
//获取
String authorization = params.getFirst("authorization");
//校验
if ("admin".equals(authorization)) {
//放行
return chain.filter(exchange);
}
//拦截
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
}
上面提到了三种过滤器,某个服务的过滤器(filters)、默认的过滤器(default-filters)、全局过滤器(GlobalFilter),如果三种过滤器都进行了配置,那么它们的执行顺序如下:
- 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
- GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
- 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增
- 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行
CROS配置
Gateway中进行跨域的配置如下:
spring:
application:
name: gatewayservice
cloud:
nacos:
server-addr: localhost:8848
discovery:
group: testgroup1
namespace: 8ff552f0-0212-43b2-8ea0-e4c2aa359084
cluster-name: HZ
gateway: #路由匹配是从前往后,依次匹配的
routes: #网关路由配置
- id: providerservice #路由id,需要唯一
uri: lb://providerservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: #路由断言,其实就是判断请求是否符合路由规则的条件
- Path=/user/** #路由匹配 只要是以/user开头的请求就会匹配到
- id: consumerservice
uri: lb://consumerservice
predicates:
- Path=/consumer/**
filters:
- AddRequestHeader=truth,This is a headr #添加请求头
default-filters:
- AddRequestHeader=truth,This is a headr1
globalcors: #跨域配置
cors-configurations:
'[/**]':
allowedOrigins: "http://localhost:8090" #允许哪些请求跨域
allowedMethods: #允许的跨域的请求方式
- GET
allowedHeaders: "*" 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 36000 #跨域检测有效期
参考
- Gateway官方文档