摘要: Zuul作为java网关届的鼻祖,2016年自研网关中间件的时候,对其源码看了很多次,经过两大互联网公司中间件的洗礼之后,目前轮到自己设计一个网关中间件纳管Spring Cloud。最近抽空把自己的理解,备注一下。由于Spring cloud整合Zuul的代码过多。本文主要介绍Spring Cloud对Netflix Zuul高度抽象封装整合部分。即spring-cloud-netflix-core的代码。
一.Spring Cloud Zuul源码分析
1.1 @EnableZuulProxy与@EnableZuulServer
如下主应用程序代码所示,我们使用Spring Cloud Zuul只需要加上@EnableZuulProxy或@EnableZuulServer两种注解就可以。
|
|
@EnableZuulProxy与@EnableZuulServer,
@EnableZuulServer - 普通Zuul Server,只支持基本的route与filter功能.
@EnableZuulProxy - 普通Zuul Server+服务发现与熔断等功能的增强版,具有反向代理功能.
1.2 @EnableZuulProxy注解入口
点开注解@EnableZuulProxy,进入到org.springframework.cloud.netflix.zuul.EnableZuulProxy,如下所示。
|
|
1.3 ZuulProxyConfiguration代码
@Import(ZuulProxyConfiguration.class),查看导入的类org.springframework.cloud.netflix.zuul.ZuulProxyConfiguration,如下所示,可以看到org.springframework.cloud.netflix.zuul.ZuulProxyConfiguration,继承了上文的ZuulConfiguration,新增了服务与实例等概念,核心重要代码已经加入注释
|
|
DiscoveryClientRouteLocator类中的locateRoutes()方法,将path与上文的ZuulRoute通过DiscoveryClientRouteLocator.locateRoutes()的对应在一起.
点击查看其父类,org.springframework.cloud.netflix.zuul.ZuulConfiguration,如下我们可以看到Netflix的Zuul-core的入口,ZuulServlet。
1.4 DiscoveryClientRouteLocator中locateRoutes
DiscoveryClientRouteLocator类中的locateRoutes的大概流程
- 将上文SimpleRouteLocator中解析出来的Route列表灌入内部的LinkedHashMap
- 抽取Route自带的serviceId,将其作为key,形成一个
staticServices
的map - 遍历DiscoveryClient拿到的serviceId列表,匹配正则形式定义的serviceId并将对应的ZuulRoute与之对应
- 调整LinkedHashMap内路由顺序,将/**挪到最后
- 微调map内容,将key值加上/或者自定义prefix
1.5 ZuulConfiguration
|
|
从ZuulConfiguration中可以拿到Simple模式下所有bean.
1.6 ZuulController整合访问的桥梁
ZuulController继承了ServletWrappingController,将当前应用中的某个Servlet直接包装为一个Controller,所有到ServletWrappingController的请求实际上是由它内部所包装的这个Servlet 实例来处理的,也就是说内部封装的Servlet实例并不对外开放,对于程序的其他范围是不可见的,适配所有的HTTP请求到内部封装的Servlet实例进行处理。它通常用于对已存的Servlet的逻辑重用上。其实这也就是Spring Cloud与Netflix Zuul整合的关键点。
|
|
1.7 ZuulProperties
|
|
其中routes对应着内部类定义ZuulRoute.
1.8 其它补充说明
org.springframework.cloud.netflix.zuul.filters.Route,是Spring Cloud 的抽象,就是上文RouteLocator
潜移默化转换的部分.
org.springframework.cloud.netflix.zuul.ZuulFilterInitializer,实现ServletContextListener
,servlet内容来自tomcat。