公司(外包)最近在做一个网关的项目,用到了zuul,出于好奇,看了下zuul的代码实现,做个简单记录。
Spring Boot版本是2.0.6.RELEASE,Spring Cloud版本是Finchley.SR1,Spring Cloud是一个版本一个代号,让人头痛。
在maven中引入zuul的依赖后,在启动类上加上@EnableZuulProxy注解就可以实现网关的功能,那么这个注解里面有什么?
可以看到,这里import了另外一个注解ZuulProxyMarkerConfiguration
通过查看这个注解使用的地方,来到ZuulProxyAutoConfiguration
可以看到这里Spring Cloud默认帮我们加载了许多的过滤器
这些过滤器没有全部贴出来,但是这些过滤器可以说就是Zuul的核心代码。同时可以看到,还有ZuulHandlerMapping、ZuulController、ZuulServlet,有没有很熟悉,是的,Zuul就是基于Spring MVC来实现的。
让我们来看一个完整的处理流程
请求会先进入Spring MVC的DispatcherServlet
进入getHandle方法
在handlerMappings中可以看到一个熟悉的ZuulHandlerMapping
直接进入ZuulHandlerMapping的lookupHandler方法
RequestContext.getCurrentContext();这里是帮我们初始化了一个requestContext上下文,在这一个请求的上下游过滤器中都可以使用,接着向下看
这个handlerMap中就是我们在配置文件中配置的路由映射关系,到这里就会跟据我们请求的url匹配出一个最佳的handler,而value就是ZuulController,然后dispatcherServlet会将请求交给ZuulController处理,进入ZuulController
可以看到这里有一个ZuulServlet,是我们之前在ZuulProxyAutoConfiguration中实例化的吗?先看一下ServletWrappingController
这里有一个servletInstance,我们猜肯定是zuulServlet的实例,但是如何实例化的呢?这里ServletWrappingController还实现了接口InitializingBean,看下它的afterPropertiesSet()方法
这里就利用了反射创建一个新的实例
到这里,就会进入ZuulServlet的处理
preRoute()、route()、postRoute()分别是执行pre/route/post三种类型的过滤器,在pre或者route类型抛出ZuulException之后,会进入error()方法,也就是执行error类型的过滤器,再执行postRoute(),如果是postRoute()阶段报错,就只会执行error(),如果抛出的异常不是ZuulException,也是会执行error(),只是zuul把异常重新包装成了ZuulException
preRoute()、route()、postRoute(),这3个方法的逻辑其实是一样的,我们挑一个看
这里会先根据过滤器的类型获取一个filter的list,然后遍历list执行所有的过滤器
执行单个的filter时,会先执行shouldFilter()方法,判断这个过滤器需不需要执行,如果返回true才会执行run方法,其实看到这里,zuul的整个调用栈就已经比较清楚了。
关于zuul是怎么实现的请求的转发,下一篇再讲。
第一次写博客,不得不说,写得真是渣!
网友评论