要想了解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

api网关揭秘--spring cloud gateway源码解析的更多相关文章

  1. Feign 系列(05)Spring Cloud OpenFeign 源码解析

    Feign 系列(05)Spring Cloud OpenFeign 源码解析 [TOC] Spring Cloud 系列目录(https://www.cnblogs.com/binarylei/p/ ...

  2. spring cloud ribbon源码解析(一)

    我们知道spring cloud中restTemplate可以通过服务名调接口,加入@loadBalanced标签就实现了负载均衡的功能,那么spring cloud内部是如何实现的呢? 通过@loa ...

  3. spring cloud ribbon源码解析(二)

    在上一篇文章中主要梳理了ribbon的执行过程,这篇主要讲讲ribbon的负载均衡,ribbon的负载均衡是通过ILoadBalancer来实现的,对ILoadBalancer有以下几个类 1.Abs ...

  4. 微服务网关实战——Spring Cloud Gateway

    导读 作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用.本文对Spring Clou ...

  5. .net core下,Ocelot网关与Spring Cloud Gateway网关的对比测试

    有感于 myzony 发布的 针对 Ocelot 网关的性能测试 ,并且公司下一步也需要对.net和java的应用做一定的整合,于是对Ocelot网关.Spring Cloud Gateway网关做个 ...

  6. Spring Security 解析(七) —— Spring Security Oauth2 源码解析

    Spring Security 解析(七) -- Spring Security Oauth2 源码解析   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因 ...

  7. spring boot @Value源码解析

    Spring boot 的@Value只能用于bean中,在bean的实例化时,会给@Value的属性赋值:如下面的例子: @SpringBootApplication @Slf4j public c ...

  8. 最全面的改造Zuul网关为Spring Cloud Gateway(包含Zuul核心实现和Spring Cloud Gateway核心实现)

    前言: 最近开发了Zuul网关的实现和Spring Cloud Gateway实现,对比Spring Cloud Gateway发现后者性能好支持场景也丰富.在高并发或者复杂的分布式下,后者限流和自定 ...

  9. 创建网关项目(Spring Cloud Gateway)

    创建网关项目 加入网关后微服务的架构图 创建项目 POM文件 <properties> <java.version>1.8</java.version> <s ...

随机推荐

  1. MySQL事物管理

    sql语句对数据库操作构成事物. 事物的特性:ACID •Atomicity(原子性):一个事物要么全都被执行,要么全都不执行,不会存在执行结束在中间环节.如果事物在执行过程中发生异常,则会回滚到事物 ...

  2. 关于Idea里设置Terminal为Git/bin/bash.exe中文乱码的问题的终极解决方案

    1.这里如果设置为Git/git-bash.exe确实不会乱码,但是每次点Idea里的Terminal都会弹出一个单独的terminal窗口而非在idea子窗口里出现: 2.因此需要设置为Git/bi ...

  3. thinkphp5省市区三级联动例子

    数据库 数据库下载地址:https://files.cnblogs.com/files/fan-bk/packet_region.zip php <?php namespace app\inde ...

  4. JObject,JArray的基本操作

    引用:https://www.cnblogs.com/dacongge/p/6957074.html 1.JObject:基本的json对象 /// <summary> /// Gets ...

  5. android项目生成aar和引用aar解决方案

    引用依赖在项目中很常见,java开发一般是引用jar,所以android大家一般也是引用jar,但是android引用jar有时候会出现各种包冲突,很头痛!, 其实android有自己独特的引用aar ...

  6. 虚拟机找不到/mnt/hgfs挂载目录——debian与 vmware

    如果在安装好 VMware Tools 并在设置里面设定好共享目录之后仍然找不到 /mnt/hgfs 默认挂载目录,那么尝试以下步骤: 1. 确认VMware Tools 和共享目录设定已经完成: 2 ...

  7. 使用jquery实现文本框输入特效:文字逐个显示逐个消失反复循环

    前两天看到某个网站上的输入框有个小特效:文字逐个显示,并且到字符串最大长度后,逐个消失,然后重新循环显示消失,循环显示字符串数组.我对这个小特效有点好奇,于是今天自己尝试用jquery写一个简单的小d ...

  8. 11g直接路径读、相关参数、10949事件介绍

    转载自刘向兵老师:http://www.askmaclean.com/archives/11g-direct-path-read-10949-_small_table_threshold-_seria ...

  9. delphi 窗体最大化 最小化

    procedure TForm1.SpeedButton2Click(Sender: TObject); begin sendmessage(form1.WindowHandle,WM_SYSCOMM ...

  10. git了解-使用笔记

    1.Git的由来与设计理念 Git是linux之父Linus Torvalds开发的,是一款最先进的项目版本控制系统. Git的由来有一个小故事,传闻起初Linux社区工作者都是通过邮件的,发送给li ...