Tomcat请求处理(三) -- coyote请求处理

来源:互联网 发布:微信运动可添加数据 编辑:程序博客网 时间:2024/05/16 19:09
在上一篇文章文章中,Tomcat的请求处理到了JIoEndpoint$Worker#run()方法的handler.process(socket)这个调用中。 

这个handler在JIoEndpoint中是这样定义的: 

Java代码  收藏代码
  1. protected Handler handler = null;  


这个Handler是在JIoEndpoint内部定义的一个接口,它的内部只有public boolean process(Socket socket);这一个方法。 

那么这个handler到底在哪里实现的呢? 

这个还要从org.apache.coyote.http11.Http11Protocol#init()中处理的,也就是在Tomcat的初始化过程中设置的。 

Java代码  收藏代码
  1. endpoint.setHandler(cHandler);  


这个cHandler就是设置的handler,它的定义如下: 

Java代码  收藏代码
  1. protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);  


这个Http11ConnectionHandler是一个Http11Protocol的内部类,它的process()方法如下所示: 

Java代码  收藏代码
  1. public boolean process(Socket socket) {  
  2.             // 获取processor  
  3.             Http11Processor processor = recycledProcessors.poll();  
  4.             try {  
  5.                 if (processor == null) {  
  6.                     // 如果为空创建一个  
  7.                     processor = createProcessor();  
  8.                 }  
  9.   
  10.                 if (processor instanceof ActionHook) {  
  11.                     // 设置Http11Processor的一个成员变量started为true  
  12.                     ((ActionHook) processor).action(ActionCode.ACTION_START, null);  
  13.                 }  
  14.                 // 设置SSL支持  
  15.                 if (proto.secure && (proto.sslImplementation != null)) {  
  16.                     processor.setSSLSupport(proto.sslImplementation.getSSLSupport(socket));  
  17.                 } else {  
  18.                     processor.setSSLSupport(null);  
  19.                 }  
  20.                 // 继续处理  
  21.                 processor.process(socket);  
  22.                 return false;  
  23.   
  24.             } catch (java.net.SocketException e) {  
  25.                 Http11Protocol.log.debug(  
  26.                         sm.getString("http11protocol.proto.socketexception.debug"), e);  
  27.             } catch (java.io.IOException e) {  
  28.                 Http11Protocol.log.debug(sm.getString("http11protocol.proto.ioexception.debug"), e);  
  29.             } catch (Throwable e) {  
  30.                 Http11Protocol.log.error(sm.getString("http11protocol.proto.error"), e);  
  31.             } finally {  
  32.                 if (processor instanceof ActionHook) {  
  33.                     // 设置Http11Processor的一个成员变量started为false  
  34.                     ((ActionHook) processor).action(ActionCode.ACTION_STOP, null);  
  35.                 }  
  36.                 // 回收processor  
  37.                 recycledProcessors.offer(processor);  
  38.             }  
  39.             return false;  
  40.         }  

首先,程序要创建一个Http11Processor对象,然后将它内部的一个标志started设为true,然后将socket对象传给Http11Processor#process()去继续请求流程。 

最后请求结束后,程序会确保started设为false,并且会回收前面使用的Http11Processor对象。 

于是,接下来请求就到了Http11Processor#process()这个方法了。 

Java代码  收藏代码
  1. public void process(Socket socket) throws IOException {  
  2.         // 请求信息,request对象  
  3.         RequestInfo rp = request.getRequestProcessor();  
  4.         // 设定请求的状态为STAGE_PARSE  
  5.         rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);  
  6.   
  7.         // 设定远端地址  
  8.         remoteAddr = null;  
  9.         remoteHost = null;  
  10.         localAddr = null;  
  11.         localName = null;  
  12.         remotePort = -1;  
  13.         localPort = -1;  
  14.   
  15.         // IO设定  
  16.         this.socket = socket;  
  17.         // 输入  
  18.         inputBuffer.setInputStream(socket.getInputStream());  
  19.         // 输出  
  20.         outputBuffer.setOutputStream(socket.getOutputStream());  
  21.   
  22.         // 错误标志  
  23.         error = false;  
  24.         keepAlive = true;  
  25.   
  26.         // 保持连接的计数器  
  27.         int keepAliveLeft = maxKeepAliveRequests;  
  28.         // 超时设置  
  29.         int soTimeout = socket.getSoTimeout();  
  30.         int oldSoTimeout = soTimeout;  
  31.   
  32.         // 当前JIoEndpoint中的已经使用的Worker与总Worker的比例  
  33.         int threadRatio = (endpoint.getCurrentThreadsBusy() * 100) / endpoint.getMaxThreads();  
  34.         if (threadRatio > 75) {// 如果使用中的Worker比例高于75%,只保持连接1次  
  35.             keepAliveLeft = 1;  
  36.         }  
  37.   
  38.         if (soTimeout != oldSoTimeout) {  
  39.             try {  
  40.                 socket.setSoTimeout(soTimeout);  
  41.             } catch (Throwable t) {  
  42.                 log.debug(sm.getString("http11processor.socket.timeout"), t);  
  43.                 error = true;  
  44.             }  
  45.         }  
  46.         // 是否被保持着连接  
  47.         boolean keptAlive = false;  
  48.   
  49.         while (started && !error && keepAlive) {// 循环处理请求  
  50.   
  51.             // Parsing the request header  
  52.             // 解析请求Header  
  53.             try {  
  54.                 if (!disableUploadTimeout && keptAlive) {  
  55.                     if (keepAliveTimeout > 0) {  
  56.                         socket.setSoTimeout(keepAliveTimeout);  
  57.                     } else if (soTimeout > 0) {  
  58.                         socket.setSoTimeout(soTimeout);  
  59.                     }  
  60.                 }  
  61.                 // 读取请求行  
  62.                 inputBuffer.parseRequestLine();  
  63.                 // 请求开始时间  
  64.                 request.setStartTime(System.currentTimeMillis());  
  65.                 keptAlive = true;  
  66.   
  67.                 if (!disableUploadTimeout) {  
  68.                     socket.setSoTimeout(timeout);  
  69.                 }  
  70.                 // 读取Header  
  71.                 inputBuffer.parseHeaders();  
  72.             } catch (IOException e) {  
  73.                 // 设置错误标志,跳出循环  
  74.                 error = true;  
  75.                 break;  
  76.             } catch (Throwable t) {  
  77.                 if (log.isDebugEnabled()) {  
  78.                     log.debug(sm.getString("http11processor.header.parse"), t);  
  79.                 }  
  80.                 // 400 - 错误的请求  
  81.                 response.setStatus(400);  
  82.                 error = true;  
  83.             }  
  84.   
  85.             rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);  
  86.             try {  
  87.                 // 准备请求  
  88.                 prepareRequest();  
  89.             } catch (Throwable t) {  
  90.                 if (log.isDebugEnabled()) {  
  91.                     log.debug(sm.getString("http11processor.request.prepare"), t);  
  92.                 }  
  93.                 response.setStatus(400);  
  94.                 error = true;  
  95.             }  
  96.   
  97.             // 设置是否请求存活  
  98.             if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)  
  99.                 keepAlive = false;  
  100.   
  101.             if (!error) {  
  102.                 try {  
  103.                     rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);  
  104.                     // adapter是org.apache.catalina.connector.CoyoteAdapter类的对象  
  105.                     adapter.service(request, response);  
  106.   
  107.                     if (keepAlive && !error) {  
  108.                         // 判断是否有异常  
  109.                         error = response.getErrorException() != null  
  110.                                 || statusDropsConnection(response.getStatus());  
  111.                     }  
  112.   
  113.                 } catch (InterruptedIOException e) {  
  114.                     error = true;  
  115.                 } catch (Throwable t) {  
  116.                     log.error(sm.getString("http11processor.request.process"), t);  
  117.                     response.setStatus(500);  
  118.                     error = true;  
  119.                 }  
  120.             }  
  121.   
  122.             // 结束请求  
  123.             try {  
  124.                 rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);  
  125.                 inputBuffer.endRequest();  
  126.             } catch (IOException e) {  
  127.                 error = true;  
  128.             } catch (Throwable t) {  
  129.                 log.error(sm.getString("http11processor.request.finish"), t);  
  130.                 response.setStatus(500);  
  131.                 error = true;  
  132.             }  
  133.             try {  
  134.                 rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);  
  135.                 outputBuffer.endRequest();  
  136.             } catch (IOException e) {  
  137.                 error = true;  
  138.             } catch (Throwable t) {  
  139.                 log.error(sm.getString("http11processor.response.finish"), t);  
  140.                 error = true;  
  141.             }  
  142.   
  143.             if (error) {  
  144.                 response.setStatus(500);  
  145.             }  
  146.             request.updateCounters();  
  147.   
  148.             rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);  
  149.   
  150.             inputBuffer.nextRequest();  
  151.             outputBuffer.nextRequest();  
  152.   
  153.         }  
  154.   
  155.         rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);  
  156.   
  157.         // 回收  
  158.         inputBuffer.recycle();  
  159.         outputBuffer.recycle();  
  160.   
  161.         sslSupport = null;  
  162.     }  


这里面需要重点说的是adapter.service(request, response);这一句,它对请求进行了进一步处理。这里的adapter是org.apache.catalina.connector.CoyoteAdapter类的对象,至于是哪里设定的这里就不详细介绍了,主要来看一下它的#service(org.apache.coyote.Request req, org.apache.coyote.Response res)方法。 

Java代码  收藏代码
  1. public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {  
  2.         // 对Coyote Request和Response进行封装  
  3.         Request request = (Request) req.getNote(ADAPTER_NOTES);  
  4.         Response response = (Response) res.getNote(ADAPTER_NOTES);  
  5.   
  6.         if (request == null) {  
  7.             // 重新创建封装的Coyote Request和Response对象  
  8.             request = (Request) connector.createRequest();  
  9.             request.setCoyoteRequest(req);  
  10.             response = (Response) connector.createResponse();  
  11.             response.setCoyoteResponse(res);  
  12.   
  13.             // 互相引用  
  14.             request.setResponse(response);  
  15.             response.setRequest(request);  
  16.   
  17.             req.setNote(ADAPTER_NOTES, request);  
  18.             res.setNote(ADAPTER_NOTES, response);  
  19.   
  20.             req.getParameters().setQueryStringEncoding(connector.getURIEncoding());  
  21.   
  22.         }  
  23.   
  24.         if (connector.getXpoweredBy()) {  
  25.             response.addHeader("X-Powered-By""Servlet/2.5");  
  26.         }  
  27.   
  28.         boolean comet = false;  
  29.   
  30.         try {  
  31.             req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());  
  32.             if (postParseRequest(req, request, res, response)) {  
  33.   
  34.                 // 调用Container继续请求  
  35.                 connector.getContainer().getPipeline().getFirst().invoke(request, response);  
  36.   
  37.                 if (request.isComet()) {  
  38.                     if (!response.isClosed() && !response.isError()) {  
  39.                         if (request.getAvailable()) {  
  40.                             if (event(req, res, SocketStatus.OPEN)) {  
  41.                                 comet = true;  
  42.                                 res.action(ActionCode.ACTION_COMET_BEGIN, null);  
  43.                             }  
  44.                         } else {  
  45.                             comet = true;  
  46.                             res.action(ActionCode.ACTION_COMET_BEGIN, null);  
  47.                         }  
  48.                     } else {  
  49.                         request.setFilterChain(null);  
  50.                     }  
  51.                 }  
  52.   
  53.             }  
  54.   
  55.             if (!comet) {  
  56.                 response.finishResponse();  
  57.                 req.action(ActionCode.ACTION_POST_REQUEST, null);  
  58.             }  
  59.   
  60.         } catch (IOException e) {  
  61.             ;  
  62.         } catch (Throwable t) {  
  63.             log.error(sm.getString("coyoteAdapter.service"), t);  
  64.         } finally {  
  65.             req.getRequestProcessor().setWorkerThreadName(null);  
  66.             // 回收  
  67.             if (!comet) {  
  68.                 request.recycle();  
  69.                 response.recycle();  
  70.             } else {  
  71.                 request.clearEncoders();  
  72.                 response.clearEncoders();  
  73.             }  
  74.         }  
  75.   
  76.     }  


下面准备总结下之前的Tomcat请求处理过程,总结出一些宏观性的东西。
0 0
原创粉丝点击