浅谈SpringCloud之zuul源码解析
zuul各版本实现存在一些微小的变化,总的实现思想未改变,以spring-cloud-netflix-core-1.3.6.RELEASE为例
一、zuul的重要的初始化类
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration
org.springframework.cloud.netflix.zuul.ZuulFilterInitializer
org.springframework.cloud.netflix.zuul.RibbonCommandFactoryConfiguration
ZuulServerAutoConfiguration
初始化路由规则
初始化一些重要的filter如PreDecorationFilter,RibbonRoutingFilter
初始化ZuulFilterInitializer
初始化ZuulHandlerMapping
代码如下
//路由规则 @Bean @ConditionalOnMissingBean(DiscoveryClientRouteLocator.class) publicDiscoveryClientRouteLocatordiscoveryRouteLocator(){ returnnewDiscoveryClientRouteLocator(this.server.getServletPrefix(),this.discovery,this.zuulProperties, this.serviceRouteMapper); } //prefilters @Bean publicPreDecorationFilterpreDecorationFilter(RouteLocatorrouteLocator,ProxyRequestHelperproxyRequestHelper){ returnnewPreDecorationFilter(routeLocator,this.server.getServletPrefix(),this.zuulProperties, proxyRequestHelper); } //routefilters @Bean publicRibbonRoutingFilterribbonRoutingFilter(ProxyRequestHelperhelper, RibbonCommandFactory>ribbonCommandFactory){ RibbonRoutingFilterfilter=newRibbonRoutingFilter(helper,ribbonCommandFactory,this.requestCustomizers); returnfilter; } @Configuration protectedstaticclassZuulFilterConfiguration{ @Autowired privateMapfilters; @Bean publicZuulFilterInitializerzuulFilterInitializer( CounterFactorycounterFactory,TracerFactorytracerFactory){ FilterLoaderfilterLoader=FilterLoader.getInstance(); FilterRegistryfilterRegistry=FilterRegistry.instance(); returnnewZuulFilterInitializer(this.filters,counterFactory,tracerFactory,filterLoader,filterRegistry); } } @Bean publicZuulControllerzuulController(){ returnnewZuulController(); } @Bean publicZuulHandlerMappingzuulHandlerMapping(RouteLocatorroutes){ ZuulHandlerMappingmapping=newZuulHandlerMapping(routes,zuulController()); mapping.setErrorController(this.errorController); returnmapping; }
ZuulProxyAutoConfiguration
zuulProxAutoConfiguration继承ZuulServerAutoConfiguration功能上和zuulServerAutoConfiguration
主要功能是增加了RibbonCommandFactoryConfiguration的配置,初始化所有的实现ribbon的方式如apache,okhttp。
ZuulFilterInitializer
该类的作用主要是把初始化的过滤器注册到zuul的FilterRegistry,FilterRegistry是一个单例用于初始化路由信息,在ZuulRunner中使用
RibbonCommandFactoryConfiguration
主要作用是配置转发的实现,实现主要有apache,okhttp
二、zuul的转发实现
首先第一步转到ZuulHandlerMapping中的lookupHandler方法,把转发转到zuulController中
@Override protectedObjectlookupHandler(StringurlPath,HttpServletRequestrequest)throwsException{ if(this.errorController!=null&&urlPath.equals(this.errorController.getErrorPath())){ returnnull; } String[]ignored=this.routeLocator.getIgnoredPaths().toArray(newString[0]); if(PatternMatchUtils.simpleMatch(ignored,urlPath)){ returnnull; } RequestContextctx=RequestContext.getCurrentContext(); if(ctx.containsKey("forward.to")){ returnnull; } if(this.dirty){ synchronized(this){ if(this.dirty){ registerHandlers(); this.dirty=false; } } } returnsuper.lookupHandler(urlPath,request); }
第一次访问时dirty为true会初始化一次请求规则如下
privatevoidregisterHandlers(){ Collectionroutes=this.routeLocator.getRoutes(); if(routes.isEmpty()){ this.logger.warn("NoroutesfoundfromRouteLocator"); } else{ for(Routeroute:routes){ registerHandler(route.getFullPath(),this.zuul); } } }
第二步ZuulController继承ServletWrappingController的会把请求转到ZuulServlet中如下
/** *@authorSpencerGibb */ publicclassZuulControllerextendsServletWrappingController{ publicZuulController(){ setServletClass(ZuulServlet.class); setServletName("zuul"); setSupportedMethods((String[])null);//Allowall } @Override publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{ try{ //Wedon'tcareabouttheotherfeaturesofthebaseclass,justwantto //handletherequest returnsuper.handleRequestInternal(request,response); } finally{ //@seecom.netflix.zuul.context.ContextLifecycleFilter.doFilter RequestContext.getCurrentContext().unset(); } } }
第三步ZuulServlet的service方法如下主要执行pre,route,postRoute三种路由器
@Override publicvoidservice(javax.servlet.ServletRequestservletRequest,javax.servlet.ServletResponseservletResponse)throwsServletException,IOException{ try{ init((HttpServletRequest)servletRequest,(HttpServletResponse)servletResponse); //Marksthisrequestashavingpassedthroughthe"Zuulengine",asopposedtoservlets //explicitlyboundinweb.xml,forwhichrequestswillnothavethesamedataattached RequestContextcontext=RequestContext.getCurrentContext(); context.setZuulEngineRan(); try{ preRoute(); }catch(ZuulExceptione){ error(e); postRoute(); return; } try{ route(); }catch(ZuulExceptione){ error(e); postRoute(); return; } try{ postRoute(); }catch(ZuulExceptione){ error(e); return; } }catch(Throwablee){ error(newZuulException(e,500,"UNHANDLED_EXCEPTION_"+e.getClass().getName())); }finally{ RequestContext.getCurrentContext().unset(); } }
四、最后由SendResponseFilter执行返回结果,filterOrder为1000所以最好post的filter不要超过1000否则影响返回结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。