浅谈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否则影响返回结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。