读书人

解析Tomcat处置请求的类Connectorlt;三amp;

发布时间: 2012-07-02 17:46:22 作者: rapoo

解析Tomcat处理请求的类Connector<三>

????? 这次主要解析采用apr方式处理请求.apr用C实现,通过JNI调用,主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能.在tomcat下配置apr步骤:

? 1.下载本地库tcnative-1.dll,放在%jdk%\bin目录下(见附件).

? 2.在server.xml里配置listener,这个配置server.xml默认是有的

?????

  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

?

? 3.在server.xml里配置apr connector

??

     <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"                connectionTimeout="20000"                redirectPort="8443" />

?

??? 在tomcat启动的时候,会调用Connector类的Start()方法,根据以上配置,Connector的start()方法里会调用Http11AprProtocol类的start()方法,如下:

??

       try {            protocolHandler.start();        } catch (Exception e) {            String errPrefix = "";            if(this.service != null) {                errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";            }            throw new LifecycleException                (errPrefix + " " + sm.getString                 ("coyoteConnector.protocolHandlerStartFailed", e));        }

?

???

?? Http11AprProtocol类的start()方法又会调用AprEndpoint类的start()方法,如下:

     try {            endpoint.start();        } catch (Exception ex) {            log.error(sm.getString("http11protocol.endpoint.starterror"), ex);            throw ex;        }

??? AprEndpoint类的start()方法如下:

public void start()        throws Exception {        // Initialize socket if not done before        if (!initialized) {            init();        }        if (!running) {            running = true;            paused = false;            // Create worker collection            if (executor == null) {                workers = new WorkerStack(maxThreads);            }            // Start poller threads            pollers = new Poller[pollerThreadCount];            for (int i = 0; i < pollerThreadCount; i++) {                pollers[i] = new Poller(false);                pollers[i].init();                pollers[i].setName(getName() + "-Poller-" + i);                pollers[i].setPriority(threadPriority);                pollers[i].setDaemon(true);                pollers[i].start();            }            // Start comet poller threads            cometPollers = new Poller[pollerThreadCount];            for (int i = 0; i < pollerThreadCount; i++) {                cometPollers[i] = new Poller(true);                cometPollers[i].init();                cometPollers[i].setName(getName() + "-CometPoller-" + i);                cometPollers[i].setPriority(threadPriority);                cometPollers[i].setDaemon(true);                cometPollers[i].start();            }            // Start sendfile threads            if (useSendfile) {                sendfiles = new Sendfile[sendfileThreadCount];                for (int i = 0; i < sendfileThreadCount; i++) {                    sendfiles[i] = new Sendfile();                    sendfiles[i].init();                    sendfiles[i].setName(getName() + "-Sendfile-" + i);                    sendfiles[i].setPriority(threadPriority);                    sendfiles[i].setDaemon(true);                    sendfiles[i].start();                }            }            // Start acceptor threads            acceptors = new Acceptor[acceptorThreadCount];            for (int i = 0; i < acceptorThreadCount; i++) {                acceptors[i] = new Acceptor();                acceptors[i].setName(getName() + "-Acceptor-" + i);                acceptors[i].setPriority(threadPriority);                acceptors[i].setDaemon(getDaemon());                acceptors[i].start();            }        }    }

??????? 该方法主要初始化接受socket的线程和处理socket的线程池.Acceptor的run()方法如下:

???

public void run() {            // Loop until we receive a shutdown command            while (running) {                // Loop if endpoint is paused                while (paused && running) {                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // Ignore                    }                }                if (!running) {                    break;                }                try {                    // Accept the next incoming connection from the server socket                    long socket = Socket.accept(serverSock);                    /*                     * In the case of a deferred accept unlockAccept needs to                     * send data. This data will be rubbish, so destroy the                     * socket and don't process it.                     */                    if (deferAccept && (paused || !running)) {                        destroySocket(socket);                        continue;                    }                    // Hand this socket off to an appropriate processor                    if (!processSocketWithOptions(socket)) {//把socket交给woker线程进行转发                        // Close socket and pool right away                        destroySocket(socket);                    }                } catch (Throwable t) {                    if (running) {                        String msg = sm.getString("endpoint.accept.fail");                        if (t instanceof Error) {                            Error e = (Error) t;                            if (e.getError() == 233) {                                // Not an error on HP-UX so log as a warning                                // so it can be filtered out on that platform                                // See bug 50273                                log.warn(msg, t);                            } else {                                log.error(msg, t);                            }                        } else {                                log.error(msg, t);                        }                    }                }            }        }    }

?

???Socket.accept(serverSock)方法的Socket类是用JNI实现的不同于java的Socket类,所以?Socket.accept(serverSock)返回的参数是long类型的.processSocketWithOptions(socket)方法如下:

????

    protected boolean processSocketWithOptions(long socket) {        try {            if (executor == null) {                getWorkerThread().assignWithOptions(socket);            } else {                executor.execute(new SocketWithOptionsProcessor(socket));            }        } catch (Throwable t) {            // This means we got an OOM or similar creating a thread, or that            // the pool and its queue are full            log.error(sm.getString("endpoint.process.fail"), t);            return false;        }        return true;    }

?

?? 再来看一下woker线程的run方法():

??

public void run() {            // Process requests until we receive a shutdown signal            while (running) {                // Wait for the next socket to be assigned                long socket = await();                if (socket == 0)                    continue;                if (!deferAccept && options) {                    if (setSocketOptions(socket)) {                        getPoller().add(socket);//将sokcet交给poller转发.poller最终会把socket交给worker处理不知道为什么这么做                    } else {                        // Close socket and pool                        destroySocket(socket);                        socket = 0;                    }                } else {                    // Process the request from this socket                    if ((status != null) && (handler.event(socket, status) == Handler.SocketState.CLOSED)) {                        // Close socket and pool                        destroySocket(socket);                        socket = 0;                    } else if ((status == null) && ((options && !setSocketOptions(socket))                            || handler.process(socket) == Handler.SocketState.CLOSED)) {//Http11AprProtocol.Http11ConnectionHandler.process(socket)处理socket                        // Close socket and pool                        destroySocket(socket);                        socket = 0;                    }                }                // Finish up this request                recycleWorkerThread(this);            }        }

?

可以看到,woker的run()方法做了两件事.1.把socket交给poller.2.直接调用处理 Http11AprProtocol.Http11ConnectionHandler.process(socket)处理socket

?handler.process(socket)方法如下:????

 public SocketState process(long socket) {            Http11AprProcessor processor = recycledProcessors.poll();            try {                if (processor == null) {                    processor = createProcessor();                }                if (processor instanceof ActionHook) {                    ((ActionHook) processor).action(ActionCode.ACTION_START, null);                }                SocketState state = processor.process(socket);//真正的解析http请求的方法                if (state == SocketState.LONG) {//如果是长连接再放回线程池处理                    // Associate the connection with the processor. The next request                     // processed by this thread will use either a new or a recycled                    // processor.                    connections.put(socket, processor);                    proto.endpoint.getCometPoller().add(socket);                } else {                    recycledProcessors.offer(processor);                }                return state;            } catch (java.net.SocketException e) {                // SocketExceptions are normal                Http11AprProtocol.log.debug                    (sm.getString                     ("http11protocol.proto.socketexception.debug"), e);            } catch (java.io.IOException e) {                // IOExceptions are normal                Http11AprProtocol.log.debug                    (sm.getString                     ("http11protocol.proto.ioexception.debug"), e);            }            // Future developers: if you discover any other            // rare-but-nonfatal exceptions, catch them here, and log as            // above.            catch (Throwable e) {                // any other exception or error is odd. Here we log it                // with "ERROR" level, so it will show up even on                // less-than-verbose logs.                Http11AprProtocol.log.error                    (sm.getString("http11protocol.proto.error"), e);            }            recycledProcessors.offer(processor);            return SocketState.CLOSED;        }

???? processor.process(socket)调用的是Http11AprProcessor类的process(long socket) 方法,用http协议对http请求进行解析

读书人网 >开源软件

热点推荐