SpringCloud之zuul源码解析


声明:本文转载自https://my.oschina.net/u/136848/blog/1621259,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

                                              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否则影响返回结果

本文发表于2018年02月11日 18:36
(c)注:本文转载自https://my.oschina.net/u/136848/blog/1621259,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1796 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1