api网关揭秘--spring cloud gateway源码解析
要想了解spring cloud gateway的源码,要熟悉spring webflux,我的上篇文章介绍了spring webflux。
1.gateway 和zuul对比
I am the author of spring cloud gateway. Zuul is built on servlet 2.5 (works with 3.x), using blocking APIs. It doesn't support any long lived connections, like websockets.
Gateway is built on Spring Framework 5, Project Reactor and Spring Boot 2 using non-blocking APIs. Websockets are supported and it's a much better developer experience since it's tightly integrated with Spring.
简单的来说:
1.zuul是基于servlet 2.5,兼容servlet3.0,使用的是阻塞API,不支持长连接如websocket
2.Gateway基于spring5,Reactor和Spring boot2使用了非阻塞API,支持websocket,和spring完美集成,对开发者友好。
另外
3.zuul2支持非阻塞API,但没有和spring cloud集成,且已经停止维护,不在考虑之列。
2.架构图
3.自动配置解析core spring.factories
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayNoLoadBalancerClientAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\ org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration org.springframework.boot.env.EnvironmentPostProcessor=\ org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor
3.1 GatewayClassPathWarningAutoConfiguration检查前端控制器
@Configuration @ConditionalOnClass(name = "org.springframework.web.servlet.DispatcherServlet") protected static class SpringMvcFoundOnClasspathConfiguration { public SpringMvcFoundOnClasspathConfiguration() { log.warn(BORDER + "Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. " + "Please remove spring-boot-starter-web dependency." + BORDER); } } @Configuration @ConditionalOnMissingClass("org.springframework.web.reactive.DispatcherHandler") protected static class WebfluxMissingFromClasspathConfiguration { public WebfluxMissingFromClasspathConfiguration() { log.warn(BORDER + "Spring Webflux is missing from the classpath, " + "which is required for Spring Cloud Gateway at this time. " + "Please add spring-boot-starter-webflux dependency." + BORDER); } }
1.若存在springmvc的前端控制器org.springframework.web.servlet.DispatcherServlet,则报警,原因是使用非阻塞的API
2.若不存在spring webflux的前端控制器org.springframework.web.reactive.DispatcherHandler,则报警,原因是需要使用非阻塞的API
3.2 网关自动配置GatewayAutoConfiguration
3.2.1 RoutePredicateHandlerMapping
@Bean public RoutePredicateHandlerMapping routePredicateHandlerMapping( FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) { return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment); }
RoutePredicateHandlerMapping继承自AbstractHandlerMapping,在此步进行路径查找
@Override protected Mono<?> getHandlerInternal(ServerWebExchange exchange) { // don't handle requests on the management port if set if (managmentPort != null && exchange.getRequest().getURI().getPort() == managmentPort.intValue()) { return Mono.empty(); } exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName()); return lookupRoute(exchange) // .log("route-predicate-handler-mapping", Level.FINER) //name this .flatMap((Function<Route, Mono<?>>) r -> { exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR); if (logger.isDebugEnabled()) { logger.debug( "Mapping [" + getExchangeDesc(exchange) + "] to " + r); } exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r); //2 return Mono.just(webHandler); }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> { exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR); if (logger.isTraceEnabled()) { logger.trace("No RouteDefinition found for [" + getExchangeDesc(exchange) + "]"); } }))); } protected Mono<Route> lookupRoute(ServerWebExchange exchange) {//1 return this.routeLocator.getRoutes() // individually filter routes so that filterWhen error delaying is not a // problem .concatMap(route -> Mono.just(route).filterWhen(r -> { // add the current route we are testing exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId()); return r.getPredicate().apply(exchange); }) // instead of immediately stopping main flux due to error, log and // swallow it .doOnError(e -> logger.error( "Error applying predicate for route: " + route.getId(), e)) .onErrorResume(e -> Mono.empty())) // .defaultIfEmpty() put a static Route not found // or .switchIfEmpty() // .switchIfEmpty(Mono.<Route>empty().log("noroute")) .next() // TODO: error handling .map(route -> { if (logger.isDebugEnabled()) { logger.debug("Route matched: " + route.getId()); } validateRoute(route, exchange); return route; }); /* * TODO: trace logging if (logger.isTraceEnabled()) { * logger.trace("RouteDefinition did not match: " + routeDefinition.getId()); } */ }
1.通过RouteLocator返回Route
关于Route的定义
private Route(String id, URI uri, int order, AsyncPredicate<ServerWebExchange> predicate, List<GatewayFilter> gatewayFilters) { this.id = id; this.uri = uri; this.order = order; this.predicate = predicate; this.gatewayFilters = gatewayFilters; }
可以看出url和gatewayFilter进行了绑定
2.将Route放入ServerWebExchange的属性中。
3.2.2 FilteringWebHandler
@Bean public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) { return new FilteringWebHandler(globalFilters); }
参考文献:
【1】https://stackoverflow.com/questions/47092048/how-spring-cloud-gateway-is-different-from-zuul
【2】https://blog.csdn.net/xuejike/article/details/81290695
相关文章
- Spring框架面试题整理
- Spring AOP的理解和使用
- 大规模 Spring Cloud 微服务无损上下线探索与实践
- spring boot:用spring security加强spring boot admin的安全(spring boot admin 2.3.0 / spring boot 2.3.3)
- Spring Cloud Alibaba | Gateway基于Nacos动态网关路由
- Spring Cloud Alibaba | Sentinel: 服务限流基础篇
- 跟我学SpringCloud | 第十四篇:Spring Cloud Gateway高级应用
- spring cloud:搭建基于consul的服务提供者集群(spring cloud hoxton sr8 / spring boot 2.3.4)
- spring data jpa实现有条件的分页查询功能
- Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现
- Spring Cloud 微服务的那点事
- 在阿里云容器服务上开发基于Docker的Spring Cloud微服务应用
- 【Spring Boot】Spring Boot经典面试题分享
- 替代 Hystrix,Spring Cloud Alibaba Sentinel 快速入门
- 006-spring cloud gateway-GatewayAutoConfiguration核心配置-GatewayProperties初始化加载、Route初始化加载
- 004-spring cloud gateway-网关请求处理过程
- 001-Spring Cloud Edgware.SR3 升级最新 Finchley.SR1,spring boot 1.5.9.RELEASE 升级2.0.4.RELEASE注意问题点
- Spring Cloud Alibaba-Sentinel-使用熔断器仪表盘监控
- Spring Cloud Gateway的常用路由断言工厂