spring cloud 入门实践系列 - zuul源码理解
2017-07-26 12:35
645 查看
从两条线分析zuul的源代码
1 启动加载配置
ZuulProxyConfiguration
2 请求访问zuul服务
http://172.16.153.1:8963/firstapi/firstapi/speak?words=zxlhgggggggg
列表内容
最终是在super的lookupHandler方法中找到handler了,也就是在AbstractUrlHandlerMapping类的lookupHandler方法中获取到。
可见path最终都是映射到同一个handler即ZuulController。
pre包含如下filter
route包含如下filter
post包含如下filter
那么对远程服务调用的封装,也是在Filter里面,我们可以看下
forward方法中的command.execute即是对远程服务的调用。
1 启动加载配置
ZuulProxyConfiguration
2 请求访问zuul服务
http://172.16.153.1:8963/firstapi/firstapi/speak?words=zxlhgggggggg
列表内容
StandardHostValve invoke方法 (tomcat) 入口
DispatcherServlet 类的doDispatch方法 拦截
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { ... try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } ... } protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
AbstractHandlerMapping 类的getHandler方法
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
AbstractUrlHandlerMapping 类的getHandlerInternal方法
protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); Object handler = lookupHandler(lookupPath, request); if (handler == null) { // We need to care for the default handler directly, since we need to // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well. Object rawHandler = null; if ("/".equals(lookupPath)) { rawHandler = getRootHandler(); } if (rawHandler == null) { rawHandler = getDefaultHandler(); } if (rawHandler != null) { // Bean name or resolved handler? if (rawHandler instanceof String) { String handlerName = (String) rawHandler; rawHandler = getApplicationContext().getBean(handlerName); } validateHandler(rawHandler, request); handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); } } if (handler != null && logger.isDebugEnabled()) { logger.debug("Mapping [" + lookupPath + "] to " + handler); } else if (handler == null && logger.isTraceEnabled()) { logger.trace("No handler mapping found for [" + lookupPath + "]"); } return handler; }
ZuulHandlerMapping 类的lookupHandler方法
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); }
最终是在super的lookupHandler方法中找到handler了,也就是在AbstractUrlHandlerMapping类的lookupHandler方法中获取到。
可见path最终都是映射到同一个handler即ZuulController。
ZuulController handler
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(); } } }
ServletWrappingController handleRequestInternal
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { this.servletInstance.service(request, response); return null; }
ZuulServlet handler
@Override public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException { try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); 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(); } }
ZuulRunner
public void preRoute() throws ZuulException { FilterProcessor.getInstance().preRoute(); } public void route() throws ZuulException { FilterProcessor.getInstance().route(); } public void postRoute() throws ZuulException { FilterProcessor.getInstance().postRoute(); }
FilterProcessor
public void preRoute() throws ZuulException { try { runFilters("pre"); } catch (ZuulException e) { throw e; } catch (Throwable e) { throw new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + e.getClass().getName()); } } public void route() throws ZuulException { try { runFilters("route"); } catch (ZuulException e) { throw e; } catch (Throwable e) { throw new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_ROUTE_FILTER_" + e.getClass().getName()); } } public void postRoute() throws ZuulException { try { runFilters("post"); } catch (ZuulException e) { throw e; } catch (Throwable e) { throw new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_POST_FILTER_" + e.getClass().getName()); } } public Object runFilters(String sType) throws Throwable { if (RequestContext.getCurrentContext().debugRouting()) { Debug.addRoutingDebug("Invoking {" + sType + "} type filters"); } boolean bResult = false; List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType); if (list != null) { for (int i = 0; i < list.size(); i++) { ZuulFilter zuulFilter = list.get(i); Object result = processZuulFilter(zuulFilter); if (result != null && result instanceof Boolean) { bResult |= ((Boolean) result); } } } return bResult; }
pre包含如下filter
route包含如下filter
post包含如下filter
那么对远程服务调用的封装,也是在Filter里面,我们可以看下
@Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); this.helper.addIgnoredHeaders(); try { RibbonCommandContext commandContext = buildCommandContext(context); ClientHttpResponse response = forward(commandContext); setResponse(response); return response; } catch (ZuulException ex) { throw new ZuulRuntimeException(ex); } catch (Exception ex) { throw new ZuulRuntimeException(ex); } } protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception { Map<String, Object> info = this.helper.debug(context.getMethod(), context.getUri(), context.getHeaders(), context.getParams(), context.getRequestEntity()); RibbonCommand command = this.ribbonCommandFactory.create(context); try { ClientHttpResponse response = command.execute(); this.helper.appendDebug(info, response.getStatusCode().value(), response.getHeaders()); return response; } catch (HystrixRuntimeException ex) { return handleException(info, ex); } }
forward方法中的command.execute即是对远程服务的调用。
相关文章推荐
- spring cloud 入门实践系列 - zuul源码理解
- spring cloud 入门实践系列 - zuul
- spring cloud 入门实践系列 - zuul
- spring cloud 入门实践系列 - feign
- spring cloud 入门实践系列 - Hystrix
- Zend Framework2.*实践系列之一 : 快速入门
- Android 源码系列之<七>从源码的角度深入理解IntentService及HandlerThread
- maven系列:实践中理解“约定优于配置”
- 云星数据---Scala实战系列(精品版)】:Scala入门教程046-Scala实战源码-Scala foreach操作
- 深入理解Tomcat系列之二:源码调试环境搭建
- Solr入门和实践以及我对Solr的8点理解
- Lattice系列FPGA入门相关6(理解SerDes之1)
- Android 源码系列之<八>从源码的角度深入理解缓存策略之LruCache
- OPEN(SAP) UI5 学习入门系列之二: 最佳实践练习(上)
- 快速入门系列--深入理解C#
- 云星数据---Scala实战系列(精品版)】:Scala入门教程010-Scala实战源码-object(类)
- 云星数据---Scala实战系列(精品版)】:Scala入门教程019-Scala实战源码-Scala 伴生类
- 自定义View系列教程04--Draw源码分析及其实践
- Android 源码系列之<三>从安全的角度深入理解BroadcastReceiver(下)
- 云星数据---Scala实战系列(精品版)】:Scala入门教程030-Scala实战源码-Scala 的特质 (接口)06