tomcat源码浅析(五)之请求的完整过程(http1.1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a040600145/article/details/68946877

    http1.1的Connector的protocolHandler为org.apache.coyote.http11.Http11Protocol。Http11Protocol的endpoint为JIoEndpoint。JIoEndpoint的handler为Http11Protocol.Http11ConnectionHandler。

    以url为http://127.0.0.1:8080/为例线程栈的信息如下:

    1.JIoEndpoint在start时会先创建Executor线程池用来执行SocketProcessor处理接收的请求,然后会创建一个接收请求线程组。

Jioendpoint.startinternal代码
  1. public void startInternal() throws Exception {  
  2.   
  3.         if (!running) {  
  4.             running = true;  
  5.             paused = false;  
  6.   
  7.             // Create worker collection  
  8.             if (getExecutor() == null) {  
  9.                 createExecutor();  
  10.             }  
  11.   
  12.             initializeConnectionLatch();  
  13.   
  14.             startAcceptorThreads();  
  15.   
  16.             // Start async timeout thread  
  17.             Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout");  
  18.             timeoutThread.setPriority(threadPriority);  
  19.             timeoutThread.setDaemon(true);  
  20.             timeoutThread.start();  
  21.         }  
  22.     }  

  

Abstractendpoint.createexecutor代码
  1. public void createExecutor() {  
  2.        internalExecutor = true;  
  3.        TaskQueue taskqueue = new TaskQueue();  
  4.        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());  
  5.        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);  
  6.        taskqueue.setParent( (ThreadPoolExecutor) executor);  
  7.    }  
Abstractendpoint.startacceptorthreads代码
  1. protected final void startAcceptorThreads() {  
  2.        int count = getAcceptorThreadCount();  
  3.        acceptors = new Acceptor[count];  
  4.   
  5.        for (int i = 0; i < count; i++) {  
  6.            acceptors[i] = createAcceptor();  
  7.            String threadName = getName() + "-Acceptor-" + i;  
  8.            acceptors[i].setThreadName(threadName);  
  9.            Thread t = new Thread(acceptors[i], threadName);  
  10.            t.setPriority(getAcceptorThreadPriority());  
  11.            t.setDaemon(getDaemon());  
  12.            t.start();  
  13.        }  
  14.    }  

     2.Acceptor讲接收到的请求socke后调用processSocketWithOptions包装成SocketWrapper并调用线程池运行SocketProcessor。

Jioendpoint.acceptor.run代码
  1. public void run() {  
  2.   
  3.             int errorDelay = 0;  
  4.   
  5.             // Loop until we receive a shutdown command  
  6.             while (running) {  
  7.   
  8.                 // Loop if endpoint is paused  
  9.                 while (paused && running) {  
  10.                     state = AcceptorState.PAUSED;  
  11.                     try {  
  12.                         Thread.sleep(50);  
  13.                     } catch (InterruptedException e) {  
  14.                         // Ignore  
  15.                     }  
  16.                 }  
  17.   
  18.                 if (!running) {  
  19.                     break;  
  20.                 }  
  21.                 state = AcceptorState.RUNNING;  
  22.   
  23.                 try {  
  24.                     //if we have reached max connections, wait  
  25.                     countUpOrAwaitConnection();  
  26.   
  27.                     Socket socket = null;  
  28.                     try {  
  29.                         // Accept the next incoming connection from the server  
  30.                         // socket  
  31.                         socket = serverSocketFactory.acceptSocket(serverSocket);  
  32.                     } catch (IOException ioe) {  
  33.                         countDownConnection();  
  34.                         // Introduce delay if necessary  
  35.                         errorDelay = handleExceptionWithDelay(errorDelay);  
  36.                         // re-throw  
  37.                         throw ioe;  
  38.                     }  
  39.                     // Successful accept, reset the error delay  
  40.                     errorDelay = 0;  
  41.   
  42.                     // Configure the socket  
  43.                     if (running && !paused && setSocketOptions(socket)) {  
  44.                         // Hand this socket off to an appropriate processor  
  45.                         if (!processSocket(socket)) {  
  46.                             countDownConnection();  
  47.                             // Close socket right away  
  48.                             closeSocket(socket);  
  49.                         }  
  50.                     } else {  
  51.                         countDownConnection();  
  52.                         // Close socket right away  
  53.                         closeSocket(socket);  
  54.                     }  
  55.                 } catch (IOException x) {  
  56.                     if (running) {  
  57.                         log.error(sm.getString("endpoint.accept.fail"), x);  
  58.                     }  
  59.                 } catch (NullPointerException npe) {  
  60.                     if (running) {  
  61.                         log.error(sm.getString("endpoint.accept.fail"), npe);  
  62.                     }  
  63.                 } catch (Throwable t) {  
  64.                     ExceptionUtils.handleThrowable(t);  
  65.                     log.error(sm.getString("endpoint.accept.fail"), t);  
  66.                 }  
  67.             }  
  68.             state = AcceptorState.ENDED;  
  69.         }  
Jioendpoint.processsocket代码
  1. protected boolean processSocket(Socket socket) {  
  2.         // Process the request from this socket  
  3.         try {  
  4.             SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);  
  5.             wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());  
  6.             wrapper.setSecure(isSSLEnabled());  
  7.             // During shutdown, executor may be null - avoid NPE  
  8.             if (!running) {  
  9.                 return false;  
  10.             }  
  11.             getExecutor().execute(new SocketProcessor(wrapper));  
  12.         } catch (RejectedExecutionException x) {  
  13.             log.warn("Socket processing request was rejected for:" + socket, x);  
  14.             return false;  
  15.         } catch (Throwable t) {  
  16.             ExceptionUtils.handleThrowable(t);  
  17.             // This means we got an OOM or similar creating a thread, or that  
  18.             // the pool and its queue are full  
  19.             log.error(sm.getString("endpoint.process.fail"), t);  
  20.             return false;  
  21.         }  
  22.         return true;  
  23.     }  

    3.SocketProcessor会调用handler的process。

Socketprocessor.run代码
  1. public void run() {  
  2.             boolean launch = false;  
  3.             synchronized (socket) {  
  4.                 try {  
  5.                     SocketState state = SocketState.OPEN;  
  6.   
  7.                     try {  
  8.                         // SSL handshake  
  9.                         serverSocketFactory.handshake(socket.getSocket());  
  10.                     } catch (Throwable t) {  
  11.                         ExceptionUtils.handleThrowable(t);  
  12.                         if (log.isDebugEnabled()) {  
  13.                             log.debug(sm.getString("endpoint.err.handshake"), t);  
  14.                         }  
  15.                         // Tell to close the socket  
  16.                         state = SocketState.CLOSED;  
  17.                     }  
  18.   
  19.                     if ((state != SocketState.CLOSED)) {  
  20.                         if (status == null) {  
  21.                             state = handler.process(socket, SocketStatus.OPEN_READ);  
  22.                         } else {  
  23.                             state = handler.process(socket, status);  
  24.                         }  
  25.                     }  
  26.                     if (state == SocketState.CLOSED) {  
  27.                         // Close socket  
  28.                         if (log.isTraceEnabled()) {  
  29.                             log.trace("Closing socket:" + socket);  
  30.                         }  
  31.                         countDownConnection();  
  32.                         try {  
  33.                             socket.getSocket().close();  
  34.                         } catch (IOException e) {  
  35.                             // Ignore  
  36.                         }  
  37.                     } else if (state == SocketState.OPEN || state == SocketState.UPGRADING  
  38.                             || state == SocketState.UPGRADING_TOMCAT || state == SocketState.UPGRADED) {  
  39.                         socket.setKeptAlive(true);  
  40.                         socket.access();  
  41.                         launch = true;  
  42.                     } else if (state == SocketState.LONG) {  
  43.                         socket.access();  
  44.                         waitingRequests.add(socket);  
  45.                     }  
  46.                 } finally {  
  47.                     if (launch) {  
  48.                         try {  
  49.                             getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN_READ));  
  50.                         } catch (RejectedExecutionException x) {  
  51.                             log.warn("Socket reprocessing request was rejected for:" + socket, x);  
  52.                             try {  
  53.                                 //unable to handle connection at this time  
  54.                                 handler.process(socket, SocketStatus.DISCONNECT);  
  55.                             } finally {  
  56.                                 countDownConnection();  
  57.                             }  
  58.   
  59.                         } catch (NullPointerException npe) {  
  60.                             if (running) {  
  61.                                 log.error(sm.getString("endpoint.launch.fail"), npe);  
  62.                             }  
  63.                         }  
  64.                     }  
  65.                 }  
  66.             }  
  67.             socket = null;  
  68.             // Finish up this request  
  69.         }  
  70.     }  

 4.Http11Protocol.Http11ConnectionHandler又会调用Processor的process方法

Abstractprotocol.process代码
  1. public SocketState process(SocketWrapper<S> wrapper,  
  2.                 SocketStatus status) {  
  3.             if (wrapper == null) {  
  4.                 // Nothing to do. Socket has been closed.  
  5.                 return SocketState.CLOSED;  
  6.             }  
  7.   
  8.             S socket = wrapper.getSocket();  
  9.             if (socket == null) {  
  10.                 // Nothing to do. Socket has been closed.  
  11.                 return SocketState.CLOSED;  
  12.             }  
  13.   
  14.             Processor<S> processor = connections.get(socket);  
  15.             if (status == SocketStatus.DISCONNECT && processor == null) {  
  16.                 // Nothing to do. Endpoint requested a close and there is no  
  17.                 // longer a processor associated with this socket.  
  18.                 return SocketState.CLOSED;  
  19.             }  
  20.   
  21.             wrapper.setAsync(false);  
  22.             ContainerThreadMarker.markAsContainerThread();  
  23.   
  24.             try {  
  25.                 if (processor == null) {  
  26.                     processor = recycledProcessors.poll();  
  27.                 }  
  28.                 if (processor == null) {  
  29.                     processor = createProcessor();  
  30.                 }  
  31.   
  32.                 initSsl(wrapper, processor);  
  33.   
  34.                 SocketState state = SocketState.CLOSED;  
  35.                 do {  
  36.                     if (status == SocketStatus.DISCONNECT &&  
  37.                             !processor.isComet()) {  
  38.                         // Do nothing here, just wait for it to get recycled  
  39.                         // Don't do this for Comet we need to generate an end  
  40.                         // event (see BZ 54022)  
  41.                     } else if (processor.isAsync() || state == SocketState.ASYNC_END) {  
  42.                         state = processor.asyncDispatch(status);  
  43.                         if (state == SocketState.OPEN) {  
  44.                             // release() won't get called so in case this request  
  45.                             // takes a long time to process, remove the socket from  
  46.                             // the waiting requests now else the async timeout will  
  47.                             // fire  
  48.                             getProtocol().endpoint.removeWaitingRequest(wrapper);  
  49.                             // There may be pipe-lined data to read. If the data  
  50.                             // isn't processed now, execution will exit this  
  51.                             // loop and call release() which will recycle the  
  52.                             // processor (and input buffer) deleting any  
  53.                             // pipe-lined data. To avoid this, process it now.  
  54.                             state = processor.process(wrapper);  
  55.                         }  
  56.                     } else if (processor.isComet()) {  
  57.                         state = processor.event(status);  
  58.                     } else if (processor.getUpgradeInbound() != null) {  
  59.                         state = processor.upgradeDispatch();  
  60.                     } else if (processor.isUpgrade()) {  
  61.                         state = processor.upgradeDispatch(status);  
  62.                     } else {  
  63.                         state = processor.process(wrapper);  
  64.                     }  
  65.   
  66.                     if (state != SocketState.CLOSED && processor.isAsync()) {  
  67.                         state = processor.asyncPostProcess();  
  68.                     }  
  69.   
  70.                     if (state == SocketState.UPGRADING) {  
  71.                         // Get the HTTP upgrade handler  
  72.                         HttpUpgradeHandler httpUpgradeHandler =  
  73.                                 processor.getHttpUpgradeHandler();  
  74.                         // Release the Http11 processor to be re-used  
  75.                         release(wrapper, processor, false, false);  
  76.                         // Create the upgrade processor  
  77.                         processor = createUpgradeProcessor(  
  78.                                 wrapper, httpUpgradeHandler);  
  79.                         // Mark the connection as upgraded  
  80.                         wrapper.setUpgraded(true);  
  81.                         // Associate with the processor with the connection  
  82.                         connections.put(socket, processor);  
  83.                         // Initialise the upgrade handler (which may trigger  
  84.                         // some IO using the new protocol which is why the lines  
  85.                         // above are necessary)  
  86.                         // This cast should be safe. If it fails the error  
  87.                         // handling for the surrounding try/catch will deal with  
  88.                         // it.  
  89.                         httpUpgradeHandler.init((WebConnection) processor);  
  90.                     } else if (state == SocketState.UPGRADING_TOMCAT) {  
  91.                         // Get the UpgradeInbound handler  
  92.                         org.apache.coyote.http11.upgrade.UpgradeInbound inbound =  
  93.                                 processor.getUpgradeInbound();  
  94.                         // Release the Http11 processor to be re-used  
  95.                         release(wrapper, processor, false, false);  
  96.                         // Create the light-weight upgrade processor  
  97.                         processor = createUpgradeProcessor(wrapper, inbound);  
  98.                         inbound.onUpgradeComplete();  
  99.                     }  
  100.                     if (getLog().isDebugEnabled()) {  
  101.                         getLog().debug("Socket: [" + wrapper +  
  102.                                 "], Status in: [" + status +  
  103.                                 "], State out: [" + state + "]");  
  104.                     }  
  105.                 } while (state == SocketState.ASYNC_END ||  
  106.                         state == SocketState.UPGRADING ||  
  107.                         state == SocketState.UPGRADING_TOMCAT);  
  108.   
  109.                 if (state == SocketState.LONG) {  
  110.                     // In the middle of processing a request/response. Keep the  
  111.                     // socket associated with the processor. Exact requirements  
  112.                     // depend on type of long poll  
  113.                     connections.put(socket, processor);  
  114.                     longPoll(wrapper, processor);  
  115.                 } else if (state == SocketState.OPEN) {  
  116.                     // In keep-alive but between requests. OK to recycle  
  117.                     // processor. Continue to poll for the next request.  
  118.                     connections.remove(socket);  
  119.                     release(wrapper, processor, false, true);  
  120.                 } else if (state == SocketState.SENDFILE) {  
  121.                     // Sendfile in progress. If it fails, the socket will be  
  122.                     // closed. If it works, the socket will be re-added to the  
  123.                     // poller  
  124.                     connections.remove(socket);  
  125.                     release(wrapper, processor, false, false);  
  126.                 } else if (state == SocketState.UPGRADED) {  
  127.                     // Need to keep the connection associated with the processor  
  128.                     connections.put(socket, processor);  
  129.                     // Don't add sockets back to the poller if this was a  
  130.                     // non-blocking write otherwise the poller may trigger  
  131.                     // multiple read events which may lead to thread starvation  
  132.                     // in the connector. The write() method will add this socket  
  133.                     // to the poller if necessary.  
  134.                     if (status != SocketStatus.OPEN_WRITE) {  
  135.                         longPoll(wrapper, processor);  
  136.                     }  
  137.                 } else {  
  138.                     // Connection closed. OK to recycle the processor. Upgrade  
  139.                     // processors are not recycled.  
  140.                     connections.remove(socket);  
  141.                     if (processor.isUpgrade()) {  
  142.                         processor.getHttpUpgradeHandler().destroy();  
  143.                     } else if (processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor) {  
  144.                         // NO-OP  
  145.                     } else {  
  146.                         release(wrapper, processor, true, false);  
  147.                     }  
  148.                 }  
  149.                 return state;  
  150.             } catch(java.net.SocketException e) {  
  151.                 // SocketExceptions are normal  
  152.                 getLog().debug(sm.getString(  
  153.                         "abstractConnectionHandler.socketexception.debug"), e);  
  154.             } catch (java.io.IOException e) {  
  155.                 // IOExceptions are normal  
  156.                 getLog().debug(sm.getString(  
  157.                         "abstractConnectionHandler.ioexception.debug"), e);  
  158.             }  
  159.             // Future developers: if you discover any other  
  160.             // rare-but-nonfatal exceptions, catch them here, and log as  
  161.             // above.  
  162.             catch (Throwable e) {  
  163.                 ExceptionUtils.handleThrowable(e);  
  164.                 // any other exception or error is odd. Here we log it  
  165.                 // with "ERROR" level, so it will show up even on  
  166.                 // less-than-verbose logs.  
  167.                 getLog().error(  
  168.                         sm.getString("abstractConnectionHandler.error"), e);  
  169.             }  
  170.             // Make sure socket/processor is removed from the list of current  
  171.             // connections  
  172.             connections.remove(socket);  
  173.             // Don't try to add upgrade processors back into the pool  
  174.             if (!(processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor)  
  175.                     && !processor.isUpgrade()) {  
  176.                 release(wrapper, processor, true, false);  
  177.             }  
  178.             return SocketState.CLOSED;  
  179.         }  

 5.Http11Processor会先调用prepareRequest解析请求的头信息后调用adapter的service。

Abstracthttp11processor.process代码
  1. public SocketState process(SocketWrapper<S> socketWrapper) throws IOException {  
  2.         RequestInfo rp = request.getRequestProcessor();  
  3.         rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);  
  4.   
  5.         // Setting up the I/O  
  6.         setSocketWrapper(socketWrapper);  
  7.         getInputBuffer().init(socketWrapper, endpoint);  
  8.         getOutputBuffer().init(socketWrapper, endpoint);  
  9.   
  10.         // Flags  
  11.         keepAlive = true;  
  12.         comet = false;  
  13.         openSocket = false;  
  14.         sendfileInProgress = false;  
  15.         readComplete = true;  
  16.         if (endpoint.getUsePolling()) {  
  17.             keptAlive = false;  
  18.         } else {  
  19.             keptAlive = socketWrapper.isKeptAlive();  
  20.         }  
  21.   
  22.         if (disableKeepAlive()) {  
  23.             socketWrapper.setKeepAliveLeft(0);  
  24.         }  
  25.   
  26.         while (!getErrorState().isError() && keepAlive && !comet && !isAsync() && upgradeInbound == null  
  27.                 && httpUpgradeHandler == null && !endpoint.isPaused()) {  
  28.   
  29.             // Parsing the request header  
  30.             try {  
  31.                 setRequestLineReadTimeout();  
  32.   
  33.                 if (!getInputBuffer().parseRequestLine(keptAlive)) {  
  34.                     if (handleIncompleteRequestLineRead()) {  
  35.                         break;  
  36.                     }  
  37.                 }  
  38.   
  39.                 if (endpoint.isPaused()) {  
  40.                     // 503 - Service unavailable  
  41.                     response.setStatus(503);  
  42.                     setErrorState(ErrorState.CLOSE_CLEAN, null);  
  43.                 } else {  
  44.                     keptAlive = true;  
  45.                     // Set this every time in case limit has been changed via JMX  
  46.                     request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());  
  47.                     request.getCookies().setLimit(getMaxCookieCount());  
  48.                     // Currently only NIO will ever return false here  
  49.                     if (!getInputBuffer().parseHeaders()) {  
  50.                         // We've read part of the request, don't recycle it  
  51.                         // instead associate it with the socket  
  52.                         openSocket = true;  
  53.                         readComplete = false;  
  54.                         break;  
  55.                     }  
  56.                     if (!disableUploadTimeout) {  
  57.                         setSocketTimeout(connectionUploadTimeout);  
  58.                     }  
  59.                 }  
  60.             } catch (IOException e) {  
  61.                 if (getLog().isDebugEnabled()) {  
  62.                     getLog().debug(sm.getString("http11processor.header.parse"), e);  
  63.                 }  
  64.                 setErrorState(ErrorState.CLOSE_NOW, e);  
  65.                 break;  
  66.             } catch (Throwable t) {  
  67.                 ExceptionUtils.handleThrowable(t);  
  68.                 UserDataHelper.Mode logMode = userDataHelper.getNextMode();  
  69.                 if (logMode != null) {  
  70.                     String message = sm.getString("http11processor.header.parse");  
  71.                     switch (logMode) {  
  72.                     case INFO_THEN_DEBUG:  
  73.                         message += sm.getString("http11processor.fallToDebug");  
  74.                         //$FALL-THROUGH$  
  75.                     case INFO:  
  76.                         getLog().info(message, t);  
  77.                         break;  
  78.                     case DEBUG:  
  79.                         getLog().debug(message, t);  
  80.                     }  
  81.                 }  
  82.                 // 400 - Bad Request  
  83.                 response.setStatus(400);  
  84.                 setErrorState(ErrorState.CLOSE_CLEAN, t);  
  85.                 getAdapter().log(request, response, 0);  
  86.             }  
  87.   
  88.             if (!getErrorState().isError()) {  
  89.                 // Setting up filters, and parse some request headers  
  90.                 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);  
  91.                 try {  
  92.                     prepareRequest();  
  93.                 } catch (Throwable t) {  
  94.                     ExceptionUtils.handleThrowable(t);  
  95.                     if (getLog().isDebugEnabled()) {  
  96.                         getLog().debug(sm.getString("http11processor.request.prepare"), t);  
  97.                     }  
  98.                     // 500 - Internal Server Error  
  99.                     response.setStatus(500);  
  100.                     setErrorState(ErrorState.CLOSE_CLEAN, t);  
  101.                     getAdapter().log(request, response, 0);  
  102.                 }  
  103.             }  
  104.   
  105.             if (maxKeepAliveRequests == 1) {  
  106.                 keepAlive = false;  
  107.             } else if (maxKeepAliveRequests > 0 && socketWrapper.decrementKeepAlive() <= 0) {  
  108.                 keepAlive = false;  
  109.             }  
  110.   
  111.             // Process the request in the adapter  
  112.             if (!getErrorState().isError()) {  
  113.                 try {  
  114.                     rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);  
  115.                     adapter.service(request, response);  
  116.                     // Handle when the response was committed before a serious  
  117.                     // error occurred.  Throwing a ServletException should both  
  118.                     // set the status to 500 and set the errorException.  
  119.                     // If we fail here, then the response is likely already  
  120.                     // committed, so we can't try and set headers.  
  121.                     if (keepAlive  
  122.                             && !getErrorState().isError()  
  123.                             && (response.getErrorException() != null || (!isAsync() && statusDropsConnection(response  
  124.                                     .getStatus())))) {  
  125.                         setErrorState(ErrorState.CLOSE_CLEAN, null);  
  126.                     }  
  127.                     setCometTimeouts(socketWrapper);  
  128.                 } catch (InterruptedIOException e) {  
  129.                     setErrorState(ErrorState.CLOSE_NOW, e);  
  130.                 } catch (HeadersTooLargeException e) {  
  131.                     getLog().error(sm.getString("http11processor.request.process"), e);  
  132.                     // The response should not have been committed but check it  
  133.                     // anyway to be safe  
  134.                     if (response.isCommitted()) {  
  135.                         setErrorState(ErrorState.CLOSE_NOW, e);  
  136.                     } else {  
  137.                         response.reset();  
  138.                         response.setStatus(500);  
  139.                         setErrorState(ErrorState.CLOSE_CLEAN, e);  
  140.                         response.setHeader("Connection""close"); // TODO: Remove  
  141.                     }  
  142.                 } catch (Throwable t) {  
  143.                     ExceptionUtils.handleThrowable(t);  
  144.                     getLog().error(sm.getString("http11processor.request.process"), t);  
  145.                     // 500 - Internal Server Error  
  146.                     response.setStatus(500);  
  147.                     setErrorState(ErrorState.CLOSE_CLEAN, t);  
  148.                     getAdapter().log(request, response, 0);  
  149.                 }  
  150.             }  
  151.   
  152.             // Finish the handling of the request  
  153.             rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);  
  154.   
  155.             if (!isAsync() && !comet) {  
  156.                 if (getErrorState().isError()) {  
  157.                     // If we know we are closing the connection, don't drain  
  158.                     // input. This way uploading a 100GB file doesn't tie up the  
  159.                     // thread if the servlet has rejected it.  
  160.                     getInputBuffer().setSwallowInput(false);  
  161.                 } else {  
  162.                     // Need to check this again here in case the response was  
  163.                     // committed before the error that requires the connection  
  164.                     // to be closed occurred.  
  165.                     checkExpectationAndResponseStatus();  
  166.                 }  
  167.                 endRequest();  
  168.             }  
  169.   
  170.             rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);  
  171.   
  172.             // If there was an error, make sure the request is counted as  
  173.             // and error, and update the statistics counter  
  174.             if (getErrorState().isError()) {  
  175.                 response.setStatus(500);  
  176.             }  
  177.             request.updateCounters();  
  178.   
  179.             if (!isAsync() && !comet || getErrorState().isError()) {  
  180.                 if (getErrorState().isIoAllowed()) {  
  181.                     getInputBuffer().nextRequest();  
  182.                     getOutputBuffer().nextRequest();  
  183.                 }  
  184.             }  
  185.   
  186.             if (!disableUploadTimeout) {  
  187.                 if (endpoint.getSoTimeout() > 0) {  
  188.                     setSocketTimeout(endpoint.getSoTimeout());  
  189.                 } else {  
  190.                     setSocketTimeout(0);  
  191.                 }  
  192.             }  
  193.   
  194.             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);  
  195.   
  196.             if (breakKeepAliveLoop(socketWrapper)) {  
  197.                 break;  
  198.             }  
  199.         }  
  200.   
  201.         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);  
  202.   
  203.         if (getErrorState().isError() || endpoint.isPaused()) {  
  204.             System.out.println("close1:" + getErrorState().name());  
  205.             return SocketState.CLOSED;  
  206.         } else if (isAsync() || comet) {  
  207.             return SocketState.LONG;  
  208.         } else if (isUpgrade()) {  
  209.             return SocketState.UPGRADING;  
  210.         } else if (getUpgradeInbound() != null) {  
  211.             return SocketState.UPGRADING_TOMCAT;  
  212.         } else {  
  213.             if (sendfileInProgress) {  
  214.                 return SocketState.SENDFILE;  
  215.             } else {  
  216.                 if (openSocket) {  
  217.                     if (readComplete) {  
  218.                         return SocketState.OPEN;  
  219.                     } else {  
  220.                         return SocketState.LONG;  
  221.                     }  
  222.                 } else {  
  223.                     System.out.println("close2");  
  224.                     return SocketState.CLOSED;  
  225.                 }  
  226.             }  
  227.         }  
  228.     }  

 6.CoyoteAdapter会先postParseRequest设置对应的Context,Wrapper解析额外的请求参数比如cookies,session等,然后调用engine的管道最终调用servlet。

扫描二维码关注公众号,回复: 4788589 查看本文章
Coyoteadapter.service代码
  1. public void service(org.apache.coyote.Request req,  
  2.                        org.apache.coyote.Response res)  
  3.        throws Exception {  
  4.   
  5.        Request request = (Request) req.getNote(ADAPTER_NOTES);  
  6.        Response response = (Response) res.getNote(ADAPTER_NOTES);  
  7.   
  8.        if (request == null) {  
  9.   
  10.            // Create objects  
  11.            request = connector.createRequest();  
  12.            request.setCoyoteRequest(req);  
  13.            response = connector.createResponse();  
  14.            response.setCoyoteResponse(res);  
  15.   
  16.            // Link objects  
  17.            request.setResponse(response);  
  18.            response.setRequest(request);  
  19.   
  20.            // Set as notes  
  21.            req.setNote(ADAPTER_NOTES, request);  
  22.            res.setNote(ADAPTER_NOTES, response);  
  23.   
  24.            // Set query string encoding  
  25.            req.getParameters().setQueryStringEncoding  
  26.                (connector.getURIEncoding());  
  27.   
  28.        }  
  29.   
  30.        if (connector.getXpoweredBy()) {  
  31.            response.addHeader("X-Powered-By", POWERED_BY);  
  32.        }  
  33.   
  34.        boolean comet = false;  
  35.        boolean async = false;  
  36.        boolean postParseSuccess = false;  
  37.   
  38.        try {  
  39.            // Parse and set Catalina and configuration specific  
  40.            // request parameters  
  41.            req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());  
  42.            postParseSuccess = postParseRequest(req, request, res, response);  
  43.            if (postParseSuccess) {  
  44.                //check valves if we support async  
  45.                request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());  
  46.                // Calling the container  
  47.                connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);  
  48.   
  49.                if (request.isComet()) {  
  50.                    if (!response.isClosed() && !response.isError()) {  
  51.                        if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {  
  52.                            // Invoke a read event right away if there are available bytes  
  53.                            if (event(req, res, SocketStatus.OPEN_READ)) {  
  54.                                comet = true;  
  55.                                res.action(ActionCode.COMET_BEGIN, null);  
  56.                            } else {  
  57.                                return;  
  58.                            }  
  59.                        } else {  
  60.                            comet = true;  
  61.                            res.action(ActionCode.COMET_BEGIN, null);  
  62.                        }  
  63.                    } else {  
  64.                        // Clear the filter chain, as otherwise it will not be reset elsewhere  
  65.                        // since this is a Comet request  
  66.                        request.setFilterChain(null);  
  67.                    }  
  68.                }  
  69.   
  70.            }  
  71.            if (request.isAsync()) {  
  72.                async = true;  
  73.                Throwable throwable =  
  74.                        (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);  
  75.   
  76.                // If an async request was started, is not going to end once  
  77.                // this container thread finishes and an error occurred, trigger  
  78.                // the async error process  
  79.                if (!request.isAsyncCompleting() && throwable != null) {  
  80.                    request.getAsyncContextInternal().setErrorState(throwable, true);  
  81.                }  
  82.            } else if (!comet) {  
  83.                try {  
  84.                    request.finishRequest();  
  85.                    response.finishResponse();  
  86.                } finally {  
  87.                    if (postParseSuccess) {  
  88.                        // Log only if processing was invoked.  
  89.                        // If postParseRequest() failed, it has already logged it.  
  90.                        // If context is null this was the start of a comet request  
  91.                        // that failed and has already been logged.  
  92.                        ((Context) request.getMappingData().context).logAccess(  
  93.                                request, response,  
  94.                                System.currentTimeMillis() - req.getStartTime(),  
  95.                                false);  
  96.                    }  
  97.                    req.action(ActionCode.POST_REQUEST , null);  
  98.                }  
  99.            }  
  100.        } catch (IOException e) {  
  101.            // Ignore  
  102.        } finally {  
  103.            req.getRequestProcessor().setWorkerThreadName(null);  
  104.            AtomicBoolean error = new AtomicBoolean(false);  
  105.            res.action(ActionCode.IS_ERROR, error);  
  106.   
  107.            // Recycle the wrapper request and response  
  108.            if (!comet && !async || error.get()) {  
  109.                request.recycle();  
  110.                response.recycle();  
  111.            } else {  
  112.                // Clear converters so that the minimum amount of memory  
  113.                // is used by this processor  
  114.                request.clearEncoders();  
  115.                response.clearEncoders();  
  116.            }  
  117.        }  
  118.    }  
Coyoteadapter.postparserequest代码
  1. protected boolean postParseRequest(org.apache.coyote.Request req,  
  2.                                        Request request,  
  3.                                        org.apache.coyote.Response res,  
  4.                                        Response response)  
  5.             throws Exception {  
  6.   
  7.         // XXX the processor may have set a correct scheme and port prior to this point,  
  8.         // in ajp13 protocols dont make sense to get the port from the connector...  
  9.         // otherwise, use connector configuration  
  10.         if (! req.scheme().isNull()) {  
  11.             // use processor specified scheme to determine secure state  
  12.             request.setSecure(req.scheme().equals("https"));  
  13.         } else {  
  14.             // use connector scheme and secure configuration, (defaults to  
  15.             // "http" and false respectively)  
  16.             req.scheme().setString(connector.getScheme());  
  17.             request.setSecure(connector.getSecure());  
  18.         }  
  19.   
  20.         // FIXME: the code below doesnt belongs to here,  
  21.         // this is only have sense  
  22.         // in Http11, not in ajp13..  
  23.         // At this point the Host header has been processed.  
  24.         // Override if the proxyPort/proxyHost are set  
  25.         String proxyName = connector.getProxyName();  
  26.         int proxyPort = connector.getProxyPort();  
  27.         if (proxyPort != 0) {  
  28.             req.setServerPort(proxyPort);  
  29.         }  
  30.         if (proxyName != null) {  
  31.             req.serverName().setString(proxyName);  
  32.         }  
  33.   
  34.         // Copy the raw URI to the decodedURI  
  35.         MessageBytes decodedURI = req.decodedURI();  
  36.         decodedURI.duplicate(req.requestURI());  
  37.   
  38.         // Parse the path parameters. This will:  
  39.         //   - strip out the path parameters  
  40.         //   - convert the decodedURI to bytes  
  41.         parsePathParameters(req, request);  
  42.   
  43.         // URI decoding  
  44.         // %xx decoding of the URL  
  45.         try {  
  46.             req.getURLDecoder().convert(decodedURI, false);  
  47.         } catch (IOException ioe) {  
  48.             res.setStatus(400);  
  49.             res.setMessage("Invalid URI: " + ioe.getMessage());  
  50.             connector.getService().getContainer().logAccess(  
  51.                     request, response, 0, true);  
  52.             return false;  
  53.         }  
  54.         // Normalization  
  55.         if (!normalize(req.decodedURI())) {  
  56.             res.setStatus(400);  
  57.             res.setMessage("Invalid URI");  
  58.             connector.getService().getContainer().logAccess(  
  59.                     request, response, 0, true);  
  60.             return false;  
  61.         }  
  62.         // Character decoding  
  63.         convertURI(decodedURI, request);  
  64.         // Check that the URI is still normalized  
  65.         if (!checkNormalize(req.decodedURI())) {  
  66.             res.setStatus(400);  
  67.             res.setMessage("Invalid URI character encoding");  
  68.             connector.getService().getContainer().logAccess(  
  69.                     request, response, 0, true);  
  70.             return false;  
  71.         }  
  72.   
  73.         // Request mapping.  
  74.         MessageBytes serverName;  
  75.         if (connector.getUseIPVHosts()) {  
  76.             serverName = req.localName();  
  77.             if (serverName.isNull()) {  
  78.                 // well, they did ask for it  
  79.                 res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);  
  80.             }  
  81.         } else {  
  82.             serverName = req.serverName();  
  83.         }  
  84.         if (request.isAsyncStarted()) {  
  85.             //TODO SERVLET3 - async  
  86.             //reset mapping data, should prolly be done elsewhere  
  87.             request.getMappingData().recycle();  
  88.         }  
  89.   
  90.         // Version for the second mapping loop and  
  91.         // Context that we expect to get for that version  
  92.         String version = null;  
  93.         Context versionContext = null;  
  94.         boolean mapRequired = true;  
  95.   
  96.         while (mapRequired) {  
  97.             // This will map the the latest version by default  
  98.             connector.getMapper().map(serverName, decodedURI, version,  
  99.                                       request.getMappingData());  
  100.             request.setContext((Context) request.getMappingData().context);  
  101.             request.setWrapper((Wrapper) request.getMappingData().wrapper);  
  102.   
  103.             // If there is no context at this point, it is likely no ROOT context  
  104.             // has been deployed  
  105.             if (request.getContext() == null) {  
  106.                 res.setStatus(404);  
  107.                 res.setMessage("Not found");  
  108.                 // No context, so use host  
  109.                 Host host = request.getHost();  
  110.                 // Make sure there is a host (might not be during shutdown)  
  111.                 if (host != null) {  
  112.                     host.logAccess(request, response, 0, true);  
  113.                 }  
  114.                 return false;  
  115.             }  
  116.   
  117.             // Now we have the context, we can parse the session ID from the URL  
  118.             // (if any). Need to do this before we redirect in case we need to  
  119.             // include the session id in the redirect  
  120.             String sessionID;  
  121.             if (request.getServletContext().getEffectiveSessionTrackingModes()  
  122.                     .contains(SessionTrackingMode.URL)) {  
  123.   
  124.                 // Get the session ID if there was one  
  125.                 sessionID = request.getPathParameter(  
  126.                         SessionConfig.getSessionUriParamName(  
  127.                                 request.getContext()));  
  128.                 if (sessionID != null) {  
  129.                     request.setRequestedSessionId(sessionID);  
  130.                     request.setRequestedSessionURL(true);  
  131.                 }  
  132.             }  
  133.   
  134.             // Look for session ID in cookies and SSL session  
  135.             parseSessionCookiesId(req, request);  
  136.             parseSessionSslId(request);  
  137.   
  138.             sessionID = request.getRequestedSessionId();  
  139.   
  140.             mapRequired = false;  
  141.             if (version != null && request.getContext() == versionContext) {  
  142.                 // We got the version that we asked for. That is it.  
  143.             } else {  
  144.                 version = null;  
  145.                 versionContext = null;  
  146.   
  147.                 Object[] contexts = request.getMappingData().contexts;  
  148.                 // Single contextVersion means no need to remap  
  149.                 // No session ID means no possibility of remap  
  150.                 if (contexts != null && sessionID != null) {  
  151.                     // Find the context associated with the session  
  152.                     for (int i = (contexts.length); i > 0; i--) {  
  153.                         Context ctxt = (Context) contexts[i - 1];  
  154.                         if (ctxt.getManager().findSession(sessionID) != null) {  
  155.                             // We found a context. Is it the one that has  
  156.                             // already been mapped?  
  157.                             if (!ctxt.equals(request.getMappingData().context)) {  
  158.                                 // Set version so second time through mapping  
  159.                                 // the correct context is found  
  160.                                 version = ctxt.getWebappVersion();  
  161.                                 versionContext = ctxt;  
  162.                                 // Reset mapping  
  163.                                 request.getMappingData().recycle();  
  164.                                 mapRequired = true;  
  165.                                 // Recycle session info in case the correct  
  166.                                 // context is configured with different settings  
  167.                                 request.recycleSessionInfo();  
  168.                             }  
  169.                             break;  
  170.                         }  
  171.                     }  
  172.                 }  
  173.             }  
  174.   
  175.             if (!mapRequired && request.getContext().getPaused()) {  
  176.                 // Found a matching context but it is paused. Mapping data will  
  177.                 // be wrong since some Wrappers may not be registered at this  
  178.                 // point.  
  179.                 try {  
  180.                     Thread.sleep(1000);  
  181.                 } catch (InterruptedException e) {  
  182.                     // Should never happen  
  183.                 }  
  184.                 // Reset mapping  
  185.                 request.getMappingData().recycle();  
  186.                 mapRequired = true;  
  187.             }  
  188.         }  
  189.   
  190.         // Possible redirect  
  191.         MessageBytes redirectPathMB = request.getMappingData().redirectPath;  
  192.         if (!redirectPathMB.isNull()) {  
  193.             String redirectPath = urlEncoder.encode(redirectPathMB.toString(), "UTF-8");  
  194.             String query = request.getQueryString();  
  195.             if (request.isRequestedSessionIdFromURL()) {  
  196.                 // This is not optimal, but as this is not very common, it  
  197.                 // shouldn't matter  
  198.                 redirectPath = redirectPath + ";" +  
  199.                         SessionConfig.getSessionUriParamName(  
  200.                             request.getContext()) +  
  201.                     "=" + request.getRequestedSessionId();  
  202.             }  
  203.             if (query != null) {  
  204.                 // This is not optimal, but as this is not very common, it  
  205.                 // shouldn't matter  
  206.                 redirectPath = redirectPath + "?" + query;  
  207.             }  
  208.             response.sendRedirect(redirectPath);  
  209.             request.getContext().logAccess(request, response, 0, true);  
  210.             return false;  
  211.         }  
  212.   
  213.         // Filter trace method  
  214.         if (!connector.getAllowTrace()  
  215.                 && req.method().equalsIgnoreCase("TRACE")) {  
  216.             Wrapper wrapper = request.getWrapper();  
  217.             String header = null;  
  218.             if (wrapper != null) {  
  219.                 String[] methods = wrapper.getServletMethods();  
  220.                 if (methods != null) {  
  221.                     for (int i=0; i<methods.length; i++) {  
  222.                         if ("TRACE".equals(methods[i])) {  
  223.                             continue;  
  224.                         }  
  225.                         if (header == null) {  
  226.                             header = methods[i];  
  227.                         } else {  
  228.                             header += ", " + methods[i];  
  229.                         }  
  230.                     }  
  231.                 }  
  232.             }  
  233.             res.setStatus(405);  
  234.             res.addHeader("Allow", header);  
  235.             res.setMessage("TRACE method is not allowed");  
  236.             request.getContext().logAccess(request, response, 0, true);  
  237.             return false;  
  238.         }  
  239.   
  240.         doConnectorAuthenticationAuthorization(req, request);  
  241.   
  242.         return true;  
  243.     }  
 7.request的Parameters不会立即解析,只有调用时才会解析
Request.getparameter代码
  1. public String getParameter(String name) {  
  2.   
  3.         if (!parametersParsed) {  
  4.             parseParameters();  
  5.         }  
  6.   
  7.         return coyoteRequest.getParameters().getParameter(name);  
  8.   
  9.     }  
 8.http1.1的实现是通过设置socket的soTimeout来复用socket。socket的soTimeout的默认时间是20000毫秒。在JIoEndpoint的Acceptor中会先调用setSocketOptions(socket)再调用processSocket(socket)。AbstractHttp11Processor的process方法在处理是接收到超时异常IOException会返回SocketState.CLOSED。
Socketproperties代码
  1. public void setProperties(Socket socket) throws SocketException{  
  2.        if (rxBufSize != null)  
  3.            socket.setReceiveBufferSize(rxBufSize.intValue());  
  4.        if (txBufSize != null)  
  5.            socket.setSendBufferSize(txBufSize.intValue());  
  6.        if (ooBInline !=null)  
  7.            socket.setOOBInline(ooBInline.booleanValue());  
  8.        if (soKeepAlive != null)  
  9.            socket.setKeepAlive(soKeepAlive.booleanValue());  
  10.        if (performanceConnectionTime != null && performanceLatency != null &&  
  11.                performanceBandwidth != null)  
  12.            socket.setPerformancePreferences(  
  13.                    performanceConnectionTime.intValue(),  
  14.                    performanceLatency.intValue(),  
  15.                    performanceBandwidth.intValue());  
  16.        if (soReuseAddress != null)  
  17.            socket.setReuseAddress(soReuseAddress.booleanValue());  
  18.        if (soLingerOn != null && soLingerTime != null)  
  19.            socket.setSoLinger(soLingerOn.booleanValue(),  
  20.                    soLingerTime.intValue());  
  21.        if (soTimeout != null && soTimeout.intValue() >= 0)  
  22.            socket.setSoTimeout(soTimeout.intValue());  
  23.        if (tcpNoDelay != null)  
  24.            socket.setTcpNoDelay(tcpNoDelay.booleanValue());  
  25.    }  

猜你喜欢

转载自blog.csdn.net/a040600145/article/details/68946877
今日推荐