spring cloud 入门实践系列

来源:互联网 发布:centos 安装桌面 编辑:程序博客网 时间:2024/06/06 03:28

从两条线分析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;    }

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即是对远程服务的调用。

原创粉丝点击