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请求处理过程,总结出一些宏观性的东西。
页:
[1]