zoukankan      html  css  js  c++  java
  • netflix zuul 1.x与zuul2.x之比较

    1.zuul 1.x的架构如下所示:

    线程模型:

    其web应用的web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
      
        <listener>
            <listener-class>com.netflix.zuul.StartServer</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>ZuulServlet</servlet-name>
            <servlet-class>com.netflix.zuul.http.ZuulServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>ZuulServlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    
        <filter>
            <filter-name>ContextLifecycleFilter</filter-name>
            <filter-class>com.netflix.zuul.context.ContextLifecycleFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>ContextLifecycleFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
      
    </web-app>

    从上面可以看出,启动时有三个主类:

    1.1. StartServer

        @Override
        public void contextInitialized(ServletContextEvent sce) {
            logger.info("starting server");
    
            // mocks monitoring infrastructure as we don't need it for this simple app
            MonitoringHelper.initMocks();
    
            // initializes groovy filesystem poller
            initGroovyFilterManager();
    
            // initializes a few java filter examples
            initJavaFilters();
        }

    1.2. ZuulServlet

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

    1.3. ContextLifecycleFilter

    public class ContextLifecycleFilter implements Filter {
    
        public void destroy() {}
    
        public void init(FilterConfig filterConfig) throws ServletException {}
    
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
            try {
                chain.doFilter(req, res);
            } finally {
                RequestContext.getCurrentContext().unset();
            }
        }
    
    }

    2. zuul2的线程模型

    其应用的web.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             version="2.5">
    
        <filter>
            <filter-name>guiceFilter</filter-name>
            <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>guiceFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <listener>
            <listener-class>com.netflix.zuul.StartServer</listener-class>
        </listener>
    
    </web-app>

    2.1. StartServer

     /**
         * Overridden solely so we can tell how much time is being spent in overall initialization. Without
         * overriding we can't tell how much time was spent in BaseServer doing its own initialization.
         *
         * @param sce
         */
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            try {
                server.start();
            } catch (Exception e) {
                LOG.error("Error while starting karyon.", e);
                throw Throwables.propagate(e);
            }
            try {
                initialize();
            } catch (Exception e) {
                e.printStackTrace();
            }
            super.contextInitialized(sce);
        }

    2.2. ZuulServlet

       @Override
        public void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException
        {
            try {
                zuulProcessor
                        .process(servletRequest, servletResponse)
                        .doOnNext(msg -> {
                            // Store this response as an attribute for any later ServletFilters that may want access to info in it.
                            servletRequest.setAttribute("_zuul_response", msg);
                        })
                        .subscribe();
            }
            catch (Throwable e) {
                LOG.error("Unexpected error running ZuulHttpProcessor for this request.", e);
                throw new ServletException("Unexpected error running ZuulHttpProcessor for this request.");
            }
        }

    2.3 ZuulHttpProcessor

    /**
     * The main processing class for Zuul.
     *
     * 1. Translates the inbound native request (ie. HttpServletRequest, or rxnetty HttpServerRequest) into a zuul HttpRequestMessage.
     * 2. Builds the filter chain and passes the request through it.
     * 3. Writes out the HttpResponseMessage to the native response object.
     */

    处理过程:

      public Observable<ZuulMessage> process(final I nativeRequest, final O nativeResponse)
        {
            // Setup the context for this request.
            final SessionContext context;
    
            // Optionally decorate the context.
            if (decorator == null) {
                context = new SessionContext();
            } else {
                context = decorator.decorate(new SessionContext());
            }
    
            return Observable.defer((Func0<Observable<ZuulMessage>>) () -> {
    
                // Build a ZuulMessage from the netty request.
                final ZuulMessage request = contextFactory.create(context, nativeRequest, nativeResponse);
    
                // Start timing the request.
                request.getContext().getTimings().getRequest().start();
    
                /*
                 * Delegate all of the filter application logic to {@link FilterProcessor}.
                 * This work is some combination of synchronous and asynchronous.
                 */
                Observable<ZuulMessage> chain = filterProcessor.applyFilterChain(request);
    
                return chain
                        .flatMap(msg -> {
                            // Wrap this in a try/catch because we need to ensure no exception stops the observable, as
                            // we need the following doOnNext to always run - as it records metrics.
                            try {
                                // Write out the response.
                                return contextFactory.write(msg, nativeResponse);
                            }
                            catch (Exception e) {
                                LOG.error("Error in writing response! request=" + request.getInfoForLogging(), e);
    
                                // Generate a default error response to be sent to client.
                                return Observable.just(new HttpResponseMessageImpl(context, ((HttpResponseMessage) msg).getOutboundRequest(), 500));
                            }
                            finally {
                                // End the timing.
                                msg.getContext().getTimings().getRequest().end();
                            }
                        })
                        .doOnError(e -> {
                            LOG.error("Unexpected error in filter chain! request=" + request.getInfoForLogging(), e);
                        })
                        .doOnNext(msg -> {
                            // Notify requestComplete listener if configured.
                            try {
                                if (requestCompleteHandler != null)
                                    requestCompleteHandler.handle(((HttpRequestMessage) request).getInboundRequest(), (HttpResponseMessage) msg);
                            }
                            catch (Exception e) {
                                LOG.error("Error in RequestCompleteHandler.", e);
                            }
                        })
                        ;
            }).finallyDo(() -> {
                // Cleanup any resources related to this request/response.
                sessionCleaner.cleanup(context);
            });
        }
    }

    参考文献:

    【1】http://techblog.netflix.com/2013/06/announcing-zuul-edge-service-in-cloud.html

    【2】http://techblog.netflix.com/2016/09/zuul-2-netflix-journey-to-asynchronous.html?utm_source=tuicool&utm_medium=referral

  • 相关阅读:
    解决ListView异步加载数据之后不能点击的问题
    android点击实现图片放大缩小 java技术博客
    关于 数据文件自增长 的一点理解
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Linux 超级用户的权利
    RAC 实例 迁移到 单实例 使用导出导入
    Shell 基本语法
    Linux 开机引导与关机过程
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Oracle RAC + Data Guard 环境搭建
  • 原文地址:https://www.cnblogs.com/davidwang456/p/6421025.html
Copyright © 2011-2022 走看看