最近一直在解决线上一个问题,表现是:

Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s。

服务器性能很好,Tomcat版本是7.0.54,配置如下:

 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="3000" minSpareThreads="800"/> <Connector executor="tomcatThreadPool" port="8084" protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="60000"
keepAliveTimeout="30000"
maxKeepAliveRequests="8000"
maxHttpHeaderSize="8192"
URIEncoding="UTF-8"
enableLookups="false"
acceptCount="1000"
disableUploadTimeout="true"
redirectPort="8443" />

事后thread dump看其实真正处于RUNNABLE状态的线程很少,绝大部分线程都处于TIMED_WAITING状态:

于是大伙都开始纠结为什么线程会涨到3000,而且发现即使峰值过了线程数并不会降下来。

我们首先想到的是:

后端应用的处理瞬间比较慢,“堵住了”导致前端线程数涨了起来。

但是优化一个版本上线后发现虽然涨的情况有所好转,但是最终线程池还是会达到3000这个最大值。

==================================分割线=========================================

以上是大背景,中间的过程省略,直接跟各位说下目前我得到的结论:

1、首先是为什么线程不释放的问题?

简单说下我验证的Tomcat(7.0.54)线程池大概的工作机制

  • Tomcat启动时如果没有请求过来,那么线程数(都是指线程池的)为0;
  • 一旦有请求,Tomcat会初始化minSapreThreads设置的线程数;
  • Tomcat不会主动对线程池进行收缩,除非确定没有任何请求的时候,Tomcat才会将线程池收缩到minSpareThreads设置的大小;
  • Tomcat6之前的版本有一个maxSpareThreads参数,但是在7中已经移除了,所以只要前面哪怕只有一个请求,Tomcat也不会释放多于空闲的线程。

至于Tomcat为什么移除maxSpareThreads这个参数,我想也是出于性能的考虑,不停的收缩线程池性能肯定不高,而多余的线程处于等待状态的好处是一有新请求过来立刻可以处理。

  • 而且大量的Tomcat线程处于等待状态不会消耗CPU,但是会消耗一些JVM存储。

补充:上面标红的一句有点问题,进一步验证发现只有使用Keep-Alive(客户端和服务端都支持)时才是这种表现,如果客户端没有使用Keep-Alive那么线程会随着TCP连接的释放而回收。

Tomcat中Keep-Alive相关的参数:

maxKeepAliveRequests:

The maximum number of HTTP requests which can be pipelined until the connection is closed by the server. Setting this attribute to 1 will disable HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 will allow an unlimited amount of pipelined or keep-alive HTTP requests. If not specified, this attribute is set to 100.

keepAliveTimeout:

The number of milliseconds this Connector will wait for another HTTP request before closing the connection. The default value is to use the value that has been set for the connectionTimeout attribute. Use a value of -1 to indicate no (i.e. infinite) timeout.

2、为什么线程池会满?

这是我现在纠结的核心。到底是不是应用的性能慢导致的,我现在的结论是有关系,但关键是并发。

  • Tomcat的线程池的线程数跟你的瞬间并发有关系,比如maxThreads设置为1000,当瞬间并发达到1000那么Tomcat就会起1000个线程来处理,这时候跟你应用的快慢关系不大。

那么是不是并发多少Tomcat就会起多少个线程呢?这里还跟Tomcat的这几个参数设置有关系,看官方的解释是最靠谱的:

maxThreads:

The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool.

maxConnections:

The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting. The default value varies by connector type. For BIO the default is the value of maxThreads unless an Executor is used in which case the default will be the value of maxThreads from the executor. For NIO the default is 10000. For APR/native, the default is 8192.

……

acceptCount:

The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.

minSpareThreads:

The minimum number of threads always kept running. If not specified, the default of 10 is used.

我简单理解就是:

maxThreads:Tomcat线程池最多能起的线程数;

maxConnections:Tomcat最多能并发处理的请求(连接);

acceptCount:Tomcat维护最大的对列数;

minSpareThreads:Tomcat初始化的线程池大小或者说Tomcat线程池最少会有这么多线程。

比较容易弄混的是maxThreads和maxConnections这两个参数:

maxThreads是指Tomcat线程池做多能起的线程数,而maxConnections则是Tomcat一瞬间做多能够处理的并发连接数。比如maxThreads=1000,maxConnections=800,假设某一瞬间的并发时1000,那么最终Tomcat的线程数将会是800,即同时处理800个请求,剩余200进入队列“排队”,如果acceptCount=100,那么有100个请求会被拒掉。
注意:根据前面所说,只是并发那一瞬间Tomcat会起800个线程处理请求,但是稳定后,某一瞬间可能只有很少的线程处于RUNNABLE状态,大部分线程是TIMED_WAITING,如果你的应用处理时间够快的话。所以真正决定Tomcat最大可能达到的线程数是maxConnections这个参数和并发数,当并发数超过这个参数则请求会排队,这时响应的快慢就看你的程序性能了。

以上的结论都是我个人验证和总结,如有不对,跪求指正!!!

聊下并发和Tomcat线程数(Updated)的更多相关文章

  1. 聊下并发和Tomcat线程数(错误更正)

    本文前半部分结论存在严重错误,请看最后2015-1-20更新部分. 最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池 ...

  2. 浅谈并发和tomcat线程数

    假设Tomcat每到固定一个时间会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s. 服务器性能很好,Tomcat版本是7.0.54,配置如下 & ...

  3. 并发和Tomcat线程数

    转自 http://zhanjindong.com 最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多 ...

  4. tomcat高并发优化的参数优化并查看tomcat线程数

    在Tomcat配置文件conf下面 server.xml 中的配置中和连接数相关的参数有: minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10 maxProcessor ...

  5. Tomcat线程数与处理速度的关系

    问题:Tomcat线程数是不是越大越好呢? 答案肯定是否定的. Tomcat的处理速度跟线程数不是完全成正比的,设置不恰当会出现相反的效果.服务的负载计算包括了CPU的使用率和资源等待. 第一种情况, ...

  6. inux下进程的最大线程数、进程最大数、进程打开的文件数

    inux下进程的最大线程数.进程最大数.进程打开的文件数 2008-12-07 23:48 =========================    如下转载自这里. linux 系统中单个进程的最大 ...

  7. linux下进程的最大线程数、进程最大数、进程打开的文件数

    linux下进程的最大线程数.进程最大数.进程打开的文件数   ===========最大线程数============== linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_TH ...

  8. 记一次生产环境tomcat线程数打满情况分析

    前言 旨在分享工作中遇到的各种问题及解决思路与方案,与大家一起学习. -- 学无止境, 加油 ! Just do it ! 问题描述 运行环境描述 tomcat-8.5 单节点(该应用集群20个节点) ...

  9. tomcat 线程数与 mysql 连接数综合调优

    目前线上系统包含 数据收集+数据分析+中心服务,三个均为 tomcat,共用一个mysql服务. 由于tomcat最大线程数200 *3 =600,最大并发时,会有600个jdbc连接.当然这是极端情 ...

随机推荐

  1. Sublime Text 之运行 ES6 (基于babel)

    本文同步自我的个人博客:http://www.52cik.com/2015/10/21/sublime-text-run-es6.html 之前在博客园里写过一篇<Sublime Text 之运 ...

  2. Object-Oriented CSS

    1.指导思想: http://oocss.org/ 2.reset.css http://meyerweb.com/eric/tools/css/reset/ 3.normalize.css http ...

  3. Sublime Text 3使用参考手册

    什么是Sublime Text? Sublime Text 是一个代码编辑器(Sublime Text 2是收费软件,但可以无限期试用),也是HTML和散文先进的文本编辑器.Sublime Text是 ...

  4. 第三十二课:JSDeferred的性能提速

    大家如果看了前面两课,就知道Deferred的静态方法next(next_default)是用setTimeout实现的(有浏览器最小时钟间隔).但是实现这种异步操作,可以有很多种方法.JSDefer ...

  5. javascript-XMLHttpRequest

    JS方法: var xmlhttp;//一定注意是写在外面的全局变量,我调了一个上午才发现. function verify(){ //使用dom方式获取文本框中的值 var userName=doc ...

  6. .net架构设计读书笔记--第二章 设计体系结构

    第五节 探索领域架构 一.领域驱动设计的价值与意义 最初在java中使用,.net要晚些才引入.领域驱动设计出现之初的争议.一个向导,少走弯路   1. 我们真的需要DDD吗? DDD并不适用于每个软 ...

  7. <supports-screens>的用法

    <supports-screens android:resizeable=["true"| "false"] android:smallScreens=[ ...

  8. COLORBOX文档

    1,flash覆盖colorbox: 2,colorbox在ie中的位置和行为异常: 3,colorbox的位置和行为异常(不区分浏览器): 4,用colorbox显示外部文档时显示不正确: 5,在i ...

  9. tuple内部方法

    代码: #tuple内部方法 ac=('a','r','6','d','a','b','b','e') print(dir(ac)) print(ac.count('a')) print(ac.ind ...

  10. HDU-1394 Minimum Inversion Number 线段树+逆序对

    仍旧在练习线段树中..这道题一开始没有完全理解搞了一上午,感到了自己的shabi.. Minimum Inversion Number Time Limit: 2000/1000 MS (Java/O ...