`
zddava
  • 浏览: 243023 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多
在上一篇文章文章中,Tomcat的请求处理到了JIoEndpoint$Worker#run()方法的handler.process(socket)这个调用中。

这个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请求处理过程,总结出一些宏观性的东西。
分享到:
评论

相关推荐

    tomcat-coyote-7.0.34-sources.jar.zip

    Coyote是Tomcat中的核心组件之一,主要负责处理HTTP请求和响应。它的设计目标是提供一个高性能、低级别的连接器,使得Tomcat可以高效地处理网络I/O操作。Coyote的设计模式采用了Java NIO(非阻塞I/O)技术,这使得它...

    tomcat-coyote.jar.zip

    而Tomcat Coyote是Tomcat核心组件之一,它负责处理HTTP请求和响应,扮演着关键的角色。本文将深入探讨Tomcat Coyote.jar的内涵及其重要性。 Tomcat Coyote是Tomcat内部的一个子项目,它的主要任务是实现Servlet 3.1...

    apache-tomcat-8.5.32-windows-x64.zip

    3. ** Coyote**:处理HTTP协议的连接器,负责接收和响应来自客户端的请求。 4. **Juli**:Tomcat的内置日志系统,用于记录服务器的活动和错误信息。 5. **Shared Libraries**:开发者可以将这些库放在特定的目录下,...

    apache-tomcat-8.5.47-windows-x64.zip

    - **Connector**:处理HTTP请求和响应,是Tomcat与Web客户端通信的桥梁。 - ** Coyote**:Tomcat的HTTP/1.1连接器,负责监听和接受来自Web客户端的连接。 - **Juli**:Tomcat的日志框架,用于记录应用程序和...

    apache-tomcat-8.5.45-windows-x64.zip

    3. ** Coyote**: Coyote是Tomcat的连接器组件,负责处理网络通信。它提供了一种机制,使得Tomcat能够监听和响应HTTP请求。 4. **Juli**: 这是Tomcat的日志系统,用于记录服务器的各种活动和错误信息。 5. **Common...

    tomcat-connectors-1.2.40-src.zip

    Tomcat Connectors,也称为Coyote,是Apache Tomcat服务器的核心组件之一,负责处理HTTP、AJP等网络协议的连接和通信。最新版本的`tomcat-connectors-1.2.40-src.zip`提供了这一关键模块的源代码,这对于开发者深入...

    tomcat-connectors-1.2.46-src

    标签“tomcat-conne”虽然不完整,但显然指的是“Tomcat连接器”,这是Tomcat中负责处理网络连接的部分,包括两个主要组件:Coyote(处理HTTP/1.x协议)和Jasper(处理JSP)。Coyote提供了一个低级别的接口来处理...

    tomcat-connectors-1.2.44-src.tar

    Tomcat Connectors,通常也被称为Coyote,是Tomcat处理HTTP连接的组件,它负责监听来自客户端的请求,并将这些请求转发到Tomcat的内部处理引擎。Coyote提供了两种主要的连接器:JK和Apr,分别对应于Java的JNI接口和...

    tomcat-connectors-1.2.27-src.tar.gz

    Adapter将Servlet容器的请求和响应对象转换为Coyote可以处理的格式,并将Coyote处理的结果转换回Servlet容器。在Tomcat中,每个Connector都有一个对应的Adapter。 2. **Protocol Handlers**:这些是处理特定网络...

    64位apache-tomcat-7.0.64-windows-x64

    - Catalina处理Servlet请求,Jasper编译并执行JSP,而Coyote负责与客户端进行网络通信。 2. **Tomcat 7.0.64版本特性**: - 改进了性能和稳定性,修复了多个安全漏洞。 - 支持Java EE 6 Web Profile,包括...

    apache-tomcat-8.0.28-windows-x64.rar

    这些组件协同工作,接收请求,处理业务逻辑,并返回响应。 **3. 安装与配置** 在Windows环境下,用户可以通过解压"apache-tomcat-8.0.28-windows-x64.rar"文件来安装Tomcat。配置主要涉及设置环境变量,如CATALINA_...

    apache-tomcat-9.0.65-windows-x64.zip

    Coyote处理网络I/O,提高了Tomcat的性能。 4. **Cluster**:如果配置了集群功能,Tomcat可以实现负载均衡和故障转移,以提高可用性和可扩展性。 5. **Manager**:这是一个Web应用程序管理工具,允许用户通过浏览器...

    tomcat 64位 windows apache-tomcat-8.0.30-windows-x64.rar

    这些改进使得Tomcat在处理高并发请求时更加高效,同时也提升了开发者的体验。 总之,Apache Tomcat 8.0.30是64位Windows环境下的强大Java Web服务器,具备丰富的功能和良好的社区支持。正确配置和使用它,能为你的...

    apache-tomcat-7.0.59-windows-x64_免安装

    - ** Coyote**:处理HTTP连接的组件,负责监听端口并响应请求。 - **Jasper**:负责JSP编译成Servlet的引擎。 - **Commons Daemon**:用于Windows平台的服务控制。 5. **安全管理:** - **设置用户和角色**:...

    apache-tomcat-7.0.56-windows-x64.rar

    2. **Tomcat架构**:Tomcat服务器主要由几个关键组件构成,包括Catalina(核心Servlet容器)、Jasper(JSP引擎)、 Coyote(HTTP/1.1协议处理)和Juli(日志系统)。这些组件协同工作,使得Tomcat能够处理Web应用...

    jakarta-tomcat-connectors-1.2.15-src.zip

    在Tomcat中,连接器主要负责处理来自网络的请求并将其传递给相应的Servlet容器,同时将Servlet的响应发送回客户端。关键组件包括 Coyote Connector(用于HTTP/HTTPS协议)和JMX(Java Management Extensions)支持,...

    apache-TOMCAT-5.5.25

    3. ** Coyote**:处理HTTP连接,是Tomcat接收和响应HTTP请求的组件。 4. **Juli**:这是Tomcat的日志系统,可以自定义日志输出格式和级别。 5. **Shared**:共享库,可以被所有Web应用程序使用。 在Apache Tomcat...

    apache-tomcat-8.0.17-windows-x64.zip

    3. ** Coyote**:这是一个HTTP协议处理器,负责处理来自Web客户端的请求,并将响应返回给客户端。 4. **Juli**:这是Tomcat的内置日志框架,可以自定义配置以满足不同日志需求。 5. **Cluster**:在集群环境中,...

    Tomcat7.0.8-win-x64x

    这个文件通常包含了Tomcat服务器的所有核心组件,如Catalina(核心Servlet容器)、 Coyote(连接器处理HTTP请求)、 Jasper(JSP编译器),以及其他必要的库和配置文件。 在实际使用中,部署Tomcat时,你需要解压这...

    最新版windows apache-tomcat-8.5.69-windows-x64.zip

    对于开发者来说,Tomcat 8.5.69提供了丰富的API和工具,如JMX(Java Management Extensions)用于监控和管理服务器状态,以及 Catalina、Coyote和 Jasper等核心组件,它们分别处理Servlet容器、HTTP协议处理和JSP...

Global site tag (gtag.js) - Google Analytics