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

[经验分享] Tomcat高性能调优方案详解

[复制链接]

尚未签到

发表于 2018-11-30 06:00:12 | 显示全部楼层 |阅读模式
  一丶原理
  概要
  Tomcat大致分为两个部分,Connector组件及Container组件。Connector组件负责控制入口连接,并关联着一个Executor。Container负责Servlet容器的实现,Executor负责具体的业务逻辑,如Servlet的执行。一个请求到达服务器后,经过以下关键几步,参见图1:
  图一
  OS与客户端握手并建立连接,并将建立的连接放入完成队列,不妨叫Acceptor Queque。这个队列的长度就是Connector的acceptCount值。
  Tomcat中的acceptor线程,不断从Acceptor Queque中获取连接。
  Acceptor Queque队列中没有连接,Acceptor线程继续监视
  Acceptor Queque队列中有新连接,Acceptor线程将检查当前的连接数是否超过了maxConnections
  如果超过maxConnections,则阻塞。直到连接数小于maxConnections,acceptor线程将请求交由Executor负责执行。
  Executor将分配worker线程来处理请求数据的读取,处理(servlet的执行)以及响应。
  参数
  acceptCount
  acceptCount 实际上是Bind Socket时候传递的backlog值,在linux平台下含义是已经建立连接还没有被应用获取的连接队列最大长度。此时,如果请求个数达到了acceptCount,新进的请求将抛出refuse connection.
  maxConnections:
  顾名思义,即Tomcat允许的同时存在的最大连接数。默认BIO模式下,这个数值等于maxThreads,即最大线程数。超过这个值后,acceptor线程被Block。新进入的连接将由acceptCount控制。当当前连接数小于这个数值时,acceptor线程被唤醒,新的连接才能进入Executor执行。
  executor
  JDK缺省的ThreadPoolExecutor的逻辑是:
  如果线程数小于coreThreadSize, 优先建立新线程。
  如果线程数大于coreThreadSize小于maxThreadSize,将请求入队列等待。
  队列满的时候,才扩充线程数直到maxThreadSize.
  当队列满,同时线程数大于maxThreadSize时,抛出异常。
  Tomcat对JDK的ThreadPoolExecutor默认行为做了修改。使用继承自***队列的LinkedBlockingQueue的TaskQueue,并改写了其入队策略,是的tomcat的Executor具有以下特性。
  只要线程不足,并且小于maxThreads, 优先建立新线程。而不是超过coreSize,先入队列。
  Executor如果发生reject,则将任务继续加入队列。而默认队列的size是Integer.MAX_VALUE,因此不会Reject.
  在配置中,Executor可以单独配置,并被整个Tomcat共享。如果不配置,则Connector组件将使用自己默认的实现。
  maxThreads
  Worker线程的最大值。每当一个请求进来时,如果当前线程数小于这个值,则创建新的线程。如果大于这个值,则查找空闲线程。如果没有空闲线程,则被Block住。
  protocol
  可以有三个取值,BIO,NIO, APR。BIO使用阻塞Socket实现,一个连接一个线程的模型。NIO使用的时候非阻塞socket实现。APR是apache实现的一个夸平台的库,也是apache http服务以来的核心网络组件。
  以上介绍的几个参数之间存在着微妙的关系。一方面可以限制过多的请求来保护系统资源,另一方面提供缓冲队列来提高系统的吞吐量。在低并发条件下,默认值基本满足要求。而在高并发的情况下,就需要根据具体的计算资源,评估以上参数的设置,来充分调动计算资源。
  二丶应用
  默认值的效果
  背景中的case除了使用异步Servlet,后端依赖的服务也全部采用异步调用。即在tomcat的woker线程中,没有任何阻塞,只是做纯粹的本地CPU计算, 为了模拟服务失败的情况,后端服务被mock住,并随机sleep 0~3s。初次使用了tomcat的默认设置(具体值参见后表中第1条)。由于后端woker线程很快(发送异步请求后就结束了),一个线程在1s内可以处理多于一个的请求。此时,如果maxConnections等于maxThreads 的值,很显然不能完全激活全部工作线程。如图2:
  图二
  300个线程,只能达到140左右的吞吐量,tomcat worker线程只有17个上下,平均响应时间已经2s多了(理论上正常平均应该1.5s),继续增加线程,返回异常,说明已经达到了极限值。可以理解为,在异步情况下,20个worker线程每秒就能处理140个请求。
  maxConnection的应用
  为了将worker线程打满,同时对后端的异步服务有足够的信心,逐步将maxConnection调整到2000,使用2000个并发打压。此时200个worker线程都工作了。吞吐量已经达到了1308(如图3),此时应该是应用最大吞吐量了。至此,初步达到了预期效果。
  图三
  NIO Connector的应用
  还有个NIO Connector,看到名字就是支持异步的IO了,在其它参数不变的情况下,换成NIO Connector。如图4所示,在吞吐量基本不变的情况下,线程数基本减少了一半。
  图四
  在启用NIO Connector,servlet及后端调用不异步的话,如图所示5,显然吞吐量上不去,而且还有所下降。
  图五
  图六
  为了充分发挥tomcat的潜能,需要综合评估这几个重要参数。当worker线程处理足够快的时候,可以适当提高maxConnections值,以便更多的请求得到处理。
  反之,如果后端线程处理较慢,则可考虑减少maxConnections及QueueSize,避免请求堆积而造成请求超时。另外NIO能更高效处理网络连接及请求。在全栈异步的情况下,能有效减少Worker线程数。


运维网声明 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-641259-1-1.html 上篇帖子: Tomcat常用设置及安全管理规范 下篇帖子: tomcat cluster和tomcat+memcached实现Session会话保持
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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