设为首页 收藏本站
查看: 555|回复: 0

[经验分享] tomcat HTTP处理—— Request的生命历程和相应Connector配置解析

[复制链接]

尚未签到

发表于 2017-2-10 06:37:51 | 显示全部楼层 |阅读模式
  Request的生命历程,可以参见常量类org.apache.coyote.Constants.java

    // Request states
public static final int STAGE_NEW = 0;
public static final int STAGE_PARSE = 1;
public static final int STAGE_PREPARE = 2;
public static final int STAGE_SERVICE = 3;
public static final int STAGE_ENDINPUT = 4;
public static final int STAGE_ENDOUTPUT = 5;
public static final int STAGE_KEEPALIVE = 6;
public static final int STAGE_ENDED = 7;
  和用到这些常量的地方 Http11Processor.java (代码贴的比较多,可以用浏览器的 查找功能来查找上面的常量)

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;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.request.prepare"), t);
}
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
keepAlive = false;
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
// Handle when the response was committed before a serious
// error occurred.  Throwing a ServletException should both
// set the status to 500 and set the errorException.
// If we fail here, then the response is likely already
// committed, so we can't try and set headers.
if(keepAlive && !error) { // Avoid checking twice.
error = response.getErrorException() != null ||
statusDropsConnection(response.getStatus());
}
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
log.error(sm.getString("http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
// Finish the handling of the request
try {
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
// If we know we are closing the connection, don't drain input.
// This way uploading a 100GB file doesn't tie up the thread
// if the servlet has rejected it.
if(error)
inputBuffer.setSwallowInput(false);
inputBuffer.endRequest();
} catch (IOException e) {
error = true;
} catch (Throwable t) {
log.error(sm.getString("http11processor.request.finish"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
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 there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
// Don't reset the param - we'll see it as ended. Next request
// will reset it
// thrA.setParam(null);
// Next request
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
// Recycle
inputBuffer.recycle();
outputBuffer.recycle();
this.socket = null;
// Recycle ssl info
sslSupport = null;
}
  Connector配置解析:
  官方文档:
  http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
  文档中讲了比较多的选项的用法,其中,我把比较重要的几个列举下:
  maxKeepAliveRequests
  在服务器关闭socket连接之前,能保持的最大请求数。
  maxThreads
  服务器的最大线程数。讲白了就是Worker的最大数目,当然如果配置开启了Executor的话,这个配置项便是没有用的。
  这里你会不会有疑问,线程数和请求数有什么关系。根据我上一篇文章tomcat分配请求 的分析,一个Worker线程对应一个请求。
  那么你会不会有更多的疑问,maxThreads如何设置得比 maxKeepAliveRequests 小会怎么办?
  请看下面这段代码
  Http11Processor.java

int keepAliveLeft = maxKeepAliveRequests;
int soTimeout = endpoint.getSoTimeout();
// When using an executor, these values may return non-positive values
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
if ((curThreads*100)/maxThreads > 75) {
keepAliveLeft = 1; // 当前使用线程是最大线程数的75%的时候,会自动禁用keepAlive
}
}

while (started && !error && keepAlive) {
……
if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
keepAlive = false;
……
}
   
  当前使用线程是最大线程的75% 的时候,会自动禁用keepAlive
  所以maxThreads设置得比maxKeepAliveRequests 小,则这个maxKeepAliveRequests 设置时没有效果的。
  当maxThreads设置肯定要比 maxKeepAliveRequests 来的大,而且 maxKeepAliveRequests 不会超过maxThreads的75%!!
  默认:maxThreads 为 200
  maxKeepAliveRequests  为100
  keepAliveTimeout
   服务器Socket读取HTTP请求行到来的限制时间。 以millionseconds为单位。默认和connectionTimeout 的值一样。
  connectionTimeout
  单位是毫秒,Connector从接受连接到提交URI请求数据的等待的时间。
  开始这个我没搞懂,不过找到了这篇文章: http://twotwoandapple.blogbus.com/logs/62770043.html  上面的解释和测试。
  也可以看下面的代码:Http11Processor.java

while (started && !error && keepAlive) {
// Parsing the request header
try {
if (keptAlive) {
if (keepAliveTimeout > 0) {
socket.setSoTimeout(keepAliveTimeout);
}
else if (soTimeout > 0) {
socket.setSoTimeout(soTimeout);
}
}
// 服务器获取客户端请求行,这里会调用inputBuffer的read 方法,引起socket阻塞,阻塞时间超过soTimeout的话就会SocketTimeOutException
inputBuffer.parseRequestLine();
  disableUploadTimeout
  是否允许在上传操作的时候给与更长的socketTimeOut时间。默认false不允许。
  如果设置为true,则默认为5分钟限制,超过5分钟则会报SocketTimeOut异常。
  如果要改这个时间,需要用这个Attribute: timeout 这个官方文档没有写,不知道为什么,可能不建议修改吧,因为5分钟是和apache 的httpd的时间保持一致的。
  类似:

    <Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" disableUploadTimeout="false" timeout="600000"/>
    其中HTTP 协议,最好参考下RFC的文档 结合Http11Protocal 和 Http11Processor来看比较好

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-339864-1-1.html 上篇帖子: Java的Eclipse与Tomcat的连接 下篇帖子: tomcat启动问题:Line: 177
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表