0
点赞
收藏
分享

微信扫一扫

tomcat 源码分析

眸晓 2022-04-05 阅读 65

1. tomcat 核心组件

Server

Service

ProtocalHanler

EndPoint

ThreadPoolExecutor

Processor

Adapater

Container

engine

host

context

wrapper

2. tomcat 启动流程

Lifecycle接口实现生命周期
LifeCycleBase生命周期的基类
Container接口实现容器的组合模块
ContainerBase容器的基类
 * <pre>
 *            start()
 *  -----------------------------
 *  |                           |
 *  | init()                    |
 * NEW -»-- INITIALIZING        |
 * | |           |              |     ------------------«-----------------------
 * | |           |auto          |     |                                        |
 * | |          \|/    start() \|/   \|/     auto          auto         stop() |
 * | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
 * | |         |                                                            |  |
 * | |destroy()|                                                            |  |
 * | --»-----«--    ------------------------«--------------------------------  ^
 * |     |          |                                                          |
 * |     |         \|/          auto                 auto              start() |
 * |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
 * |    \|/                               ^                     |  ^
 * |     |               stop()           |                     |  |
 * |     |       --------------------------                     |  |
 * |     |       |                                              |  |
 * |     |       |    destroy()                       destroy() |  |
 * |     |    FAILED ----»------ DESTROYING ---«-----------------  |
 * |     |                        ^     |                          |
 * |     |     destroy()          |     |auto                      |
 * |     --------»-----------------    \|/                         |
 * |                                 DESTROYED                     |
 * |                                                               |
 * |                            stop()                             |
 * ----»-----------------------------»------------------------------

核心类图

PlantUml

@startuml tomcat

Bootstrap -> Bootstrap: main()
Bootstrap -> Catalina : load()
Catalina ->  StandardServer: initInternal()
StandardServer -> StandardService : initInternal()
StandardService -> StandardEngine : initInternal()
StandardService  -> Executor : init()
StandardService  -> mapperListener : init()
Bootstrap -> Catalina: start()
Catalina -> StandardServer : startInternal()
StandardServer -> StandardService : startInternal()
StandardService -> StandardEngine : startInternal()
StandardService -> StandardThreadExecutor : startInternal()
StandardService  -> mapperListener :  startInternal()
StandardEngine  -> StandardHost : startInternal()
StandardHost -> HostConfig : lifecycleEvent()  
HostConfig -> HostConfig :deployApps()
HostConfig -> StandardContext:
StandardContext ->  ServletContainerInitializer : startInternal() 
ServletContainerInitializer  -> SpringServletContainerInitializer: onStratUp()
@enduml

 

3. tomcat 核心请求流程

 

核心是Pipeline-Valve 是责任链模式

在基类ContainerBase中构建一个Pipeline数组作为责任链

以StandardEngine容器为例 

    /**
     * Create a new StandardEngine component with the default basic Valve.
     */
    public StandardEngine() {

        super();
        // 在构造方法中塞入StandardEngineValve 最为最后一个Valve
        pipeline.setBasic(new StandardEngineValve());
        /* Set the jmvRoute using the system property jvmRoute */
        try {
            setJvmRoute(System.getProperty("jvmRoute"));
        } catch(Exception ex) {
            log.warn(sm.getString("standardEngine.jvmRouteFail"));
        }
        // By default, the engine will hold the reloading thread
        backgroundProcessorDelay = 10;

    }

执行下一个容器的Valve

还是以StandardEngine为例子

 /**
     * Select the appropriate child Host to process this request,
     * based on the requested server name.  If no matching Host can
     * be found, return an appropriate HTTP error.
     *
     * @param request Request to be processed
     * @param response Response to be produced
     *
     * @exception IOException if an input/output error occurred
     * @exception ServletException if a servlet error occurred
     */
    @Override
    public final void invoke(Request request, Response response)
        throws IOException, ServletException {

        // Select the Host to be used for this Request
        Host host = request.getHost();
        if (host == null) {
            // HTTP 0.9 or HTTP 1.0 request without a host when no default host
            // is defined.
            // Don't overwrite an existing error
            if (!response.isError()) {
                response.sendError(404);
            }
            return;
        }
        if (request.isAsyncSupported()) {
            request.setAsyncSupported(host.getPipeline().isAsyncSupported());
        }

        // Ask this Host to process this request
        // 执行 host的一个Valve
        host.getPipeline().getFirst().invoke(request, response);
    }

执行当前容器的Valve

以AbstractAccessLogValve为例子

 /**
     * Log a message summarizing the specified request and response, according
     * to the format specified by the <code>pattern</code> property.
     *
     * @param request Request being processed
     * @param response Response being processed
     *
     * @exception IOException if an input/output error has occurred
     * @exception ServletException if a servlet error has occurred
     */
    @Override
    public void invoke(Request request, Response response) throws IOException,
            ServletException {
        if (tlsAttributeRequired) {
            // The log pattern uses TLS attributes. Ensure these are populated
            // before the request is processed because with NIO2 it is possible
            // for the connection to be closed (and the TLS info lost) before
            // the access log requests the TLS info. Requesting it now causes it
            // to be cached in the request.
            request.getAttribute(Globals.CERTIFICATES_ATTR);
        }
        if (cachedElements != null) {
            for (CachedElement element : cachedElements) {
                element.cache(request);
            }
        }
        getNext().invoke(request, response);
    }

举报

相关推荐

0 条评论