spring cloud 入门实践系列 – zuul源码理解

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取 2000+ 道 Java 面试题

从两条线分析zuul的源代码

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;
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

        24 

        25 

        26 

        27 

        28 

        29 

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;
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

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;
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

        24 

        25 

        26 

        27 

        28 

        29 

        30 

        31 

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);
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

最终是在super的lookupHandler方法中找到handler了,也就是在AbstractUrlHandlerMapping类的lookupHandler方法中获取到。
20191123100195\_1.png
可见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();
            }
        }

    }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

ServletWrappingController handleRequestInternal

    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
                throws Exception {

            this.servletInstance.service(request, response);
            return null;
        }

        1 

        2 

        3 

        4 

        5 

        6 

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();
            }
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

        24 

        25 

        26 

        27 

        28 

        29 

        30 

        31 

        32 

        33 

        34 

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();
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

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;
        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

        24 

        25 

        26 

        27 

        28 

        29 

        30 

        31 

        32 

        33 

        34 

        35 

        36 

        37 

        38 

        39 

        40 

        41 

        42 

        43 

        44 

pre包含如下filter
20191123100195\_2.png
route包含如下filter
20191123100195\_3.png
post包含如下filter
20191123100195\_4.png

那么对远程服务调用的封装,也是在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);
            }

        }

        1 

        2 

        3 

        4 

        5 

        6 

        7 

        8 

        9 

        10 

        11 

        12 

        13 

        14 

        15 

        16 

        17 

        18 

        19 

        20 

        21 

        22 

        23 

        24 

        25 

        26 

        27 

        28 

        29 

        30 

        31 

        32 

        33 

        34 

forward方法中的command.execute即是对远程服务的调用。

                                                <link rel="stylesheet" href="http://csdnimg.cn/release/phoenix/production/markdown_views-68a8aad09e.css">
                                    </div>

来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring cloud 入门实践系列 – zuul源码理解

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏