Tomcat请求处理(三) -- coyote请求处理
来源:互联网 发布:微信运动可添加数据 编辑:程序博客网 时间:2024/05/16 19:09
在上一篇文章文章中,Tomcat的请求处理到了JIoEndpoint$Worker#run()方法的handler.process(socket)这个调用中。
这个handler在JIoEndpoint中是这样定义的:
这个Handler是在JIoEndpoint内部定义的一个接口,它的内部只有public boolean process(Socket socket);这一个方法。
那么这个handler到底在哪里实现的呢?
这个还要从org.apache.coyote.http11.Http11Protocol#init()中处理的,也就是在Tomcat的初始化过程中设置的。
这个cHandler就是设置的handler,它的定义如下:
这个Http11ConnectionHandler是一个Http11Protocol的内部类,它的process()方法如下所示:
首先,程序要创建一个Http11Processor对象,然后将它内部的一个标志started设为true,然后将socket对象传给Http11Processor#process()去继续请求流程。
最后请求结束后,程序会确保started设为false,并且会回收前面使用的Http11Processor对象。
于是,接下来请求就到了Http11Processor#process()这个方法了。
这里面需要重点说的是adapter.service(request, response);这一句,它对请求进行了进一步处理。这里的adapter是org.apache.catalina.connector.CoyoteAdapter类的对象,至于是哪里设定的这里就不详细介绍了,主要来看一下它的#service(org.apache.coyote.Request req, org.apache.coyote.Response res)方法。
下面准备总结下之前的Tomcat请求处理过程,总结出一些宏观性的东西。
这个handler在JIoEndpoint中是这样定义的:
- protected Handler handler = null;
这个Handler是在JIoEndpoint内部定义的一个接口,它的内部只有public boolean process(Socket socket);这一个方法。
那么这个handler到底在哪里实现的呢?
这个还要从org.apache.coyote.http11.Http11Protocol#init()中处理的,也就是在Tomcat的初始化过程中设置的。
- endpoint.setHandler(cHandler);
这个cHandler就是设置的handler,它的定义如下:
- protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);
这个Http11ConnectionHandler是一个Http11Protocol的内部类,它的process()方法如下所示:
- public boolean process(Socket socket) {
- // 获取processor
- Http11Processor processor = recycledProcessors.poll();
- try {
- if (processor == null) {
- // 如果为空创建一个
- processor = createProcessor();
- }
- if (processor instanceof ActionHook) {
- // 设置Http11Processor的一个成员变量started为true
- ((ActionHook) processor).action(ActionCode.ACTION_START, null);
- }
- // 设置SSL支持
- if (proto.secure && (proto.sslImplementation != null)) {
- processor.setSSLSupport(proto.sslImplementation.getSSLSupport(socket));
- } else {
- processor.setSSLSupport(null);
- }
- // 继续处理
- processor.process(socket);
- return false;
- } catch (java.net.SocketException e) {
- Http11Protocol.log.debug(
- sm.getString("http11protocol.proto.socketexception.debug"), e);
- } catch (java.io.IOException e) {
- Http11Protocol.log.debug(sm.getString("http11protocol.proto.ioexception.debug"), e);
- } catch (Throwable e) {
- Http11Protocol.log.error(sm.getString("http11protocol.proto.error"), e);
- } finally {
- if (processor instanceof ActionHook) {
- // 设置Http11Processor的一个成员变量started为false
- ((ActionHook) processor).action(ActionCode.ACTION_STOP, null);
- }
- // 回收processor
- recycledProcessors.offer(processor);
- }
- return false;
- }
首先,程序要创建一个Http11Processor对象,然后将它内部的一个标志started设为true,然后将socket对象传给Http11Processor#process()去继续请求流程。
最后请求结束后,程序会确保started设为false,并且会回收前面使用的Http11Processor对象。
于是,接下来请求就到了Http11Processor#process()这个方法了。
- public void process(Socket socket) throws IOException {
- // 请求信息,request对象
- RequestInfo rp = request.getRequestProcessor();
- // 设定请求的状态为STAGE_PARSE
- rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
- // 设定远端地址
- remoteAddr = null;
- remoteHost = null;
- localAddr = null;
- localName = null;
- remotePort = -1;
- localPort = -1;
- // IO设定
- this.socket = socket;
- // 输入
- inputBuffer.setInputStream(socket.getInputStream());
- // 输出
- outputBuffer.setOutputStream(socket.getOutputStream());
- // 错误标志
- error = false;
- keepAlive = true;
- // 保持连接的计数器
- int keepAliveLeft = maxKeepAliveRequests;
- // 超时设置
- int soTimeout = socket.getSoTimeout();
- int oldSoTimeout = soTimeout;
- // 当前JIoEndpoint中的已经使用的Worker与总Worker的比例
- int threadRatio = (endpoint.getCurrentThreadsBusy() * 100) / endpoint.getMaxThreads();
- if (threadRatio > 75) {// 如果使用中的Worker比例高于75%,只保持连接1次
- keepAliveLeft = 1;
- }
- if (soTimeout != oldSoTimeout) {
- try {
- socket.setSoTimeout(soTimeout);
- } catch (Throwable t) {
- log.debug(sm.getString("http11processor.socket.timeout"), t);
- error = true;
- }
- }
- // 是否被保持着连接
- boolean keptAlive = false;
- while (started && !error && keepAlive) {// 循环处理请求
- // Parsing the request header
- // 解析请求Header
- try {
- if (!disableUploadTimeout && keptAlive) {
- if (keepAliveTimeout > 0) {
- socket.setSoTimeout(keepAliveTimeout);
- } else if (soTimeout > 0) {
- socket.setSoTimeout(soTimeout);
- }
- }
- // 读取请求行
- inputBuffer.parseRequestLine();
- // 请求开始时间
- request.setStartTime(System.currentTimeMillis());
- keptAlive = true;
- if (!disableUploadTimeout) {
- socket.setSoTimeout(timeout);
- }
- // 读取Header
- inputBuffer.parseHeaders();
- } catch (IOException e) {
- // 设置错误标志,跳出循环
- error = true;
- break;
- } catch (Throwable t) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.header.parse"), t);
- }
- // 400 - 错误的请求
- response.setStatus(400);
- error = true;
- }
- rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
- try {
- // 准备请求
- prepareRequest();
- } catch (Throwable t) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("http11processor.request.prepare"), t);
- }
- response.setStatus(400);
- error = true;
- }
- // 设置是否请求存活
- if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
- keepAlive = false;
- if (!error) {
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
- // adapter是org.apache.catalina.connector.CoyoteAdapter类的对象
- adapter.service(request, response);
- if (keepAlive && !error) {
- // 判断是否有异常
- error = response.getErrorException() != null
- || statusDropsConnection(response.getStatus());
- }
- } catch (InterruptedIOException e) {
- error = true;
- } catch (Throwable t) {
- log.error(sm.getString("http11processor.request.process"), t);
- response.setStatus(500);
- error = true;
- }
- }
- // 结束请求
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
- inputBuffer.endRequest();
- } catch (IOException e) {
- error = true;
- } catch (Throwable t) {
- log.error(sm.getString("http11processor.request.finish"), t);
- response.setStatus(500);
- error = true;
- }
- try {
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
- outputBuffer.endRequest();
- } catch (IOException e) {
- error = true;
- } catch (Throwable t) {
- log.error(sm.getString("http11processor.response.finish"), t);
- error = true;
- }
- if (error) {
- response.setStatus(500);
- }
- request.updateCounters();
- rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
- inputBuffer.nextRequest();
- outputBuffer.nextRequest();
- }
- rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
- // 回收
- inputBuffer.recycle();
- outputBuffer.recycle();
- sslSupport = null;
- }
这里面需要重点说的是adapter.service(request, response);这一句,它对请求进行了进一步处理。这里的adapter是org.apache.catalina.connector.CoyoteAdapter类的对象,至于是哪里设定的这里就不详细介绍了,主要来看一下它的#service(org.apache.coyote.Request req, org.apache.coyote.Response res)方法。
- public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {
- // 对Coyote Request和Response进行封装
- Request request = (Request) req.getNote(ADAPTER_NOTES);
- Response response = (Response) res.getNote(ADAPTER_NOTES);
- if (request == null) {
- // 重新创建封装的Coyote Request和Response对象
- request = (Request) connector.createRequest();
- request.setCoyoteRequest(req);
- response = (Response) connector.createResponse();
- response.setCoyoteResponse(res);
- // 互相引用
- request.setResponse(response);
- response.setRequest(request);
- req.setNote(ADAPTER_NOTES, request);
- res.setNote(ADAPTER_NOTES, response);
- req.getParameters().setQueryStringEncoding(connector.getURIEncoding());
- }
- if (connector.getXpoweredBy()) {
- response.addHeader("X-Powered-By", "Servlet/2.5");
- }
- boolean comet = false;
- try {
- req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
- if (postParseRequest(req, request, res, response)) {
- // 调用Container继续请求
- connector.getContainer().getPipeline().getFirst().invoke(request, response);
- if (request.isComet()) {
- if (!response.isClosed() && !response.isError()) {
- if (request.getAvailable()) {
- if (event(req, res, SocketStatus.OPEN)) {
- comet = true;
- res.action(ActionCode.ACTION_COMET_BEGIN, null);
- }
- } else {
- comet = true;
- res.action(ActionCode.ACTION_COMET_BEGIN, null);
- }
- } else {
- request.setFilterChain(null);
- }
- }
- }
- if (!comet) {
- response.finishResponse();
- req.action(ActionCode.ACTION_POST_REQUEST, null);
- }
- } catch (IOException e) {
- ;
- } catch (Throwable t) {
- log.error(sm.getString("coyoteAdapter.service"), t);
- } finally {
- req.getRequestProcessor().setWorkerThreadName(null);
- // 回收
- if (!comet) {
- request.recycle();
- response.recycle();
- } else {
- request.clearEncoders();
- response.clearEncoders();
- }
- }
- }
下面准备总结下之前的Tomcat请求处理过程,总结出一些宏观性的东西。
0 0
- Tomcat请求处理(三) -- coyote请求处理
- 浅读Tomcat源码(三)---请求处理
- 浅读Tomcat源码(三)---请求处理
- (三)tomcat如何处理请求资源路径
- tomcat请求处理分析(三) 绑定本地端口监听请求
- tomcat请求处理流程
- tomcat处理请求流程
- tomcat处理请求
- Tomcat请求处理流程
- Tomcat处理请求过程
- tomcat 处理请求过程
- Tomcat请求处理过程
- tomcat 请求处理模型
- tomcat处理请求
- Tomcat请求处理(二) -- 请求处理框架
- Tomcat - 处理HTTP请求过程
- Tomcat请求处理控制结构
- tomcat处理请求的过程
- Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy8
- python字符串和变量相加时出现,coercing to unicode need string or buffer nonetype found python 错误的解决
- FileReader FileWriter 源码分析
- 去除字符串中的数字
- 什么是SICL,什么是VISA
- Tomcat请求处理(三) -- coyote请求处理
- JSTL标签库———XML标签库
- HashMap
- 了解最新动态,提升你IT职业生涯的8种方法
- 同步方法和同步代码块
- Tomcat请求处理(二) -- 请求处理框架
- LINUX下三个内核文件详解
- Windows使用Xmanager远程登录Centos方法
- HDOJ-2026