二、tomcat中的HTTP实现
tomcat中http的实现是在Http11*Processor中的process方法中做的。之所以加上*号是因为有Http11Processor,Http11AprProcessor,Http11NioProcessor三种,为什么有三种这里就不做说明,我们仅选第一个即也是最简单的来分析。
下面重点对keepAlive的实现做一下分析。
1、变量说明
keepAlive
布尔型
是否保持keepAlive状态,true表示保持,false表示不保持
maxKeepAliveRequests
int型
最大的保持keepAlive状态的请求数,也就是第一次发出请求建立连接和保持keepAlive后后续的请求之和的最大值,因此,这个最大值是包括第一次建立连接的请求的。因此若其等于1的话,就表示在建立请求之后不能保持keepAlive状态
keepAliveLeft
int型
剩余的可以保持keepAlive的请求数,一开始等于maxKeepAliveRequests 。因此若其等于1的话,就表示除去第一次建立连接外,之后不能保持keepAlive状态
keptAlive
布尔型
表示是第一次请求还是保持keepAlive后的后续请求,false表示是第一次,true表示保持keepAlive后的后续请求
keepAliveTimeout
int型
单位millisecond
保持keepAlive后设置的可以等待下一次请求的时间
soTimeout
int型
单位millisecond
默认的socket timeout 时间,即从设置socket.setSoTimeout后开始计时的等待下一次tcp请求或者可以理解为tcp输入的最长时间,超过这个时间tcp失效
disableUploadTimeout
布尔型
是否为上传设置一个不同的socket timeout时间,false表示不设置,true表示设置
2、重要方法说明
socket.setSoTimeout
设置一个时间,设置后开始计时,在这个时间里等待下一次tcp请求或者可以理解为tcp输入,若没有等到,则tcp失效
3、代码实现
首先,变量声明:
//默认是要保持keepAlive状态的
keepAlive = true;
//剩余的可以保持keepAlive的请求数=最大的保持keepAlive状态的请求数
int keepAliveLeft = maxKeepAliveRequests;
//默认的socket timeout 时间
int soTimeout = endpoint.getSoTimeout();
//当前使用的线程个数
int curThreads = endpoint.getCurrentThreadsBusy();
//可以使用的最大线程个数
int maxThreads = endpoint.getMaxThreads();
if (curThreads > 0 && maxThreads > 0) {
// Only auto-disable keep-alive if the current thread
// usage % can be calculated correctly
//当前使用的线程个数占可以使用的最大线程个数的比率大于0.75
if ((curThreads*100)/maxThreads > 75) {
//剩余的可以保持keepAlive的请求数为1,除去首次建立连接的一次后
//为0, 即首次连接后不能继续保持keepAlive状态
keepAliveLeft = 1;
}
}
try {
//首次设置socket timeout 时间
socket.setSoTimeout(soTimeout);
} catch (Throwable t) {
log.debug(
sm.getString("http11processor.socket.timeout"), t);
error = true;
}
进入循环
//之后处理请求、http协议的处理都在这个循环里进行。http协议里就包括
//keepAlive的实现。
while (started && !error && keepAlive && !endpoint.isPaused())
// Parsing the request header
try {
if (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(soTimeout);
} else {
socket.setSoTimeout(timeout);
}
inputBuffer.parseHeaders();
} catch (IOException e) {
error = true;
break;
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.header.parse"), t);
}
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}