浅谈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) public discoveryclientroutelocator discoveryroutelocator() { return new discoveryclientroutelocator(this.server.getservletprefix(), this.discovery, this.zuulproperties, this.serviceroutemapper); } // pre filters @bean public predecorationfilter predecorationfilter(routelocator routelocator, proxyrequesthelper proxyrequesthelper) { return new predecorationfilter(routelocator, this.server.getservletprefix(), this.zuulproperties, proxyrequesthelper); } // route filters @bean public ribbonroutingfilter ribbonroutingfilter(proxyrequesthelper helper, ribboncommandfactory<?> ribboncommandfactory) { ribbonroutingfilter filter = new ribbonroutingfilter(helper, ribboncommandfactory, this.requestcustomizers); return filter; } @configuration protected static class zuulfilterconfiguration { @autowired private map<string, zuulfilter> filters; @bean public zuulfilterinitializer zuulfilterinitializer( counterfactory counterfactory, tracerfactory tracerfactory) { filterloader filterloader = filterloader.getinstance(); filterregistry filterregistry = filterregistry.instance(); return new zuulfilterinitializer(this.filters, counterfactory, tracerfactory, filterloader, filterregistry); } } @bean public zuulcontroller zuulcontroller() { return new zuulcontroller(); } @bean public zuulhandlermapping zuulhandlermapping(routelocator routes) { zuulhandlermapping mapping = new zuulhandlermapping(routes, zuulcontroller()); mapping.seterrorcontroller(this.errorcontroller); return mapping; }
zuulproxyautoconfiguration
zuulproxautoconfiguration继承zuulserverautoconfiguration功能上和zuulserverautoconfiguration
主要功能是增加了ribboncommandfactoryconfiguration的配置,初始化所有的实现ribbon的方式如apache,okhttp。
zuulfilterinitializer
该类的作用主要是把初始化的过滤器注册到zuul的filterregistry,filterregistry是一个单例用于初始化路由信息,在zuulrunner中使用
ribboncommandfactoryconfiguration
主要作用是配置转发的实现,实现主要有apache,okhttp
二、zuul的转发实现
首先第一步转到zuulhandlermapping中的lookuphandler方法,把转发转到zuulcontroller中
@override protected object lookuphandler(string urlpath, httpservletrequest request) throws exception { if (this.errorcontroller != null && urlpath.equals(this.errorcontroller.geterrorpath())) { return null; } string[] ignored = this.routelocator.getignoredpaths().toarray(new string[0]); if (patternmatchutils.simplematch(ignored, urlpath)) { return null; } requestcontext ctx = requestcontext.getcurrentcontext(); if (ctx.containskey("forward.to")) { return null; } if (this.dirty) { synchronized (this) { if (this.dirty) { registerhandlers(); this.dirty = false; } } } return super.lookuphandler(urlpath, request); }
第一次访问时dirty为true会初始化一次请求规则如下
private void registerhandlers() { collection<route> routes = this.routelocator.getroutes(); if (routes.isempty()) { this.logger.warn("no routes found from routelocator"); } else { for (route route : routes) { registerhandler(route.getfullpath(), this.zuul); } } }
第二步zuulcontroller继承servletwrappingcontroller的会把请求转到zuulservlet中如下
/** * @author spencer gibb */ public class zuulcontroller extends servletwrappingcontroller { public zuulcontroller() { setservletclass(zuulservlet.class); setservletname("zuul"); setsupportedmethods((string[]) null); // allow all } @override public modelandview handlerequest(httpservletrequest request, httpservletresponse response) throws exception { try { // we don't care about the other features of the base class, just want to // handle the request return super.handlerequestinternal(request, response); } finally { // @see com.netflix.zuul.context.contextlifecyclefilter.dofilter requestcontext.getcurrentcontext().unset(); } } }
第三步zuulservlet的service方法如下主要执行pre,route,postroute三种路由器
@override public void service(javax.servlet.servletrequest servletrequest, javax.servlet.servletresponse servletresponse) throws servletexception, ioexception { try { init((httpservletrequest) servletrequest, (httpservletresponse) servletresponse); // marks this request as having passed through the "zuul engine", as opposed to servlets // explicitly bound in web.xml, for which requests will not have the same data attached requestcontext context = requestcontext.getcurrentcontext(); context.setzuulengineran(); try { preroute(); } catch (zuulexception e) { error(e); postroute(); return; } try { route(); } catch (zuulexception e) { error(e); postroute(); return; } try { postroute(); } catch (zuulexception e) { error(e); return; } } catch (throwable e) { error(new zuulexception(e, 500, "unhandled_exception_" + e.getclass().getname())); } finally { requestcontext.getcurrentcontext().unset(); } }
四、最后由sendresponsefilter执行返回结果,filterorder为1000所以最好post的filter不要超过1000否则影响返回结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。