在中大型系统中,Gateway网关发挥着关键的作用,Gateway可以运用在许多应用场景,如接口限流、日志监控、授权认证等等。下面对过往的Gateway知识做一个归纳与总结。
路由是Gateway网关中的基础组件,它由一个org.springframework.cloud.gateway.route.RouteDefinition来描述,在RouteDefinition中包含了几个属性,即构造Route所需的基本元素:
id: 路由唯一ID
uri: 转发地址
predicate:断言
filter:路由过滤器
metadata: 其他信息
order: 排序
其中,URI转发地址可以支持
http:http协议
ws: websocket协议
lb:配置注册中心的负载均衡
既可以通过application或者yml配置,也可以通过自定义Bean通过代码注入。最终都会被加载进入内存,构造为一个RouteDefinition对象。
yml或者application
spring:
cloud:
gateway:
routes:
- id: user
uri: lb://user-center
predicates:
- Path=/user/**
如果使用自定义Bean构造注册:
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
// 构建多个路由routes
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 具体路由地址
routes.route("user-center",
r -> r.path("/msb/**").uri("http://localhost:9001/nacos-provider")).build();
// 返回所有路由规则
return routes.build();
}
在org.springframework.cloud.gateway.route.RouteDefinition中描述了,一个路由可以包含多个断言和多个过滤器。
断言用于判断是否采用本路由来转发,起到判断作用。开发者可以使用系统断言,也可以使用自定义断言。
系统自带断言
在上述yml配置中:
spring:
cloud:
gateway:
routes:
- id: user
uri: lb://user-center
predicates:
- Path=/user/**
采用了Path断言器,其对应的断言类为
这是系统自带的断言器,从源码中可以看到,出了PathRoutePredicateFactory, 还有其他很多种断言,这些断言命名都遵从断言规范,以XXXRoutePredicateFactory来命名,并且继承断言抽象父类AbstractRoutePredicateFactory,实现apply()方法, 通过该方法返回结果判断断言是否满足。
自定义断言
除了使用系统自带的断言,也可以自定义断言。规范按照以XXXRoutePredicateFactory来命名,并且继承断言抽象父类AbstractRoutePredicateFactory,实现apply()方法。可以实现自己的业务逻辑。
创建好后,通过在yml或者自定义路由Bean中配置该断言即可。
过滤器有两种
1.路由过滤器,路由过滤器和断言一样,属于org.springframework.cloud.gateway.route.RouteDefinition的成员。
2.全局过滤器,全局过滤器影响所有的请求。
路由过滤器
路由过滤器位于路由转发之前,用于处理和过滤请求数据。和断言一样,系统自带了很多过滤器。
它的设计原理和断言一样,以XXXGatewayFilterFactory命名,并且继承父类抽象过滤工厂AbstractGatewayFilterFactory,实现apply方法,在该方法中处理过滤器逻辑。
自定义路由过滤器
依葫芦画瓢,自定义一个类,以XXXGatewayFilterFactory命名,并且继承父类抽象过滤工厂AbstractGatewayFilterFactory,实现apply方法,在该方法中处理自定义的过滤器逻辑。
全局过滤器 GlobalFilter
全局过滤器GlobalFilter是一个顶级接口,所有实现了GlobalFilter的实现类,都属于全局过滤器。如果存在多个全局过滤器,则按order优先级顺序来执行。
自定义全局过滤器
如果我们要处理全局的请求或者进行全局拦截,可以实现GlobalFilter接口,自定义全局过滤器。
public class AgeRoute implements GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 业务处理
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
// 放行
return chain.filter(exchange.mutate().build());
}
}
全局过滤器中,将会得到两个参数:ServerWebExchange exchange, GatewayFilterChain chain
ServerWebExchange是Webflux框架中的定义,可以获取Http请求和Http响应对象。类似Servlet框架中的HttpServeltRequest和HttpServletResponse对象一样。GatewayFilterChain是网关过滤链表。
Webflux是什么?与Spring MVC有什么关联?
Webflux是Spring Gateway的核心框架,一套非阻塞式异步IO框架。网关的核心作用是进行路由转发,大部分的时间消耗在网络IO上,因此对于IO密集型服务,通过非阻塞式异步架构可以有效利用CPU,并且处理高并发请求。
Gateway的底层依赖Netty服务组件,然后将相关的http协议请求封装为了一个ServerWebExchange对象。
Servlet是由Web容器封装的对象,如Tomcat容器,它将请求封装为了HttpServeltRequest和HttpServletResponse两个对象。
Spring MVC是一套同步阻塞IO框架,并发力度有限。
在Webflux框架中,与Spring MVC一样拥有前端控制器,名称叫做DispatcherHandler。
进入DispatcherHandler的handler方法后,先是通过RequestMapping,拿到HandlerMethod处理器;
在通过HandlerMethod寻找合适的HandlerAdapter;
拿到合适的适配器对象之后,根据不同规则的Handler执行不同的Handler,这里就包含Controller
因为Gateway是Webflux框架,因此它也可以作为一个微服务处理业务逻辑。
可以写Controller、Service等等,访问数据库、缓存等等。
不过作为一个网关职责,不建议写太多的业务逻辑,可以处理一些简单的业务逻辑。具体的业务职责还是交给业务微服务。
Gateway可以有很多应用,比如
日志监控
系统限流
权限认证
路由转发
负载均衡
等等