做外贸网站案例,做网站用哪个写比较好,wordpress与joomla哪个好,淘宝网页制作视频教程转载自 干货 | Tomcat 连接数与线程池详解
前言
在使用tomcat时#xff0c;经常会遇到连接数、线程数之类的配置问题#xff0c;要真正理解这些概念#xff0c;必须先了解Tomcat的连接器#xff08;Connector#xff09;。
在前面的文章 详解Tomcat配置文件server.xml…转载自 干货 | Tomcat 连接数与线程池详解
前言
在使用tomcat时经常会遇到连接数、线程数之类的配置问题要真正理解这些概念必须先了解Tomcat的连接器Connector。
在前面的文章 详解Tomcat配置文件server.xml 中写到过Connector的主要功能是接收连接请求创建Request和Response对象用于和请求端交换数据然后分配线程让Engine也就是Servlet容器来处理这个请求并把产生的Request和Response对象传给Engine。当Engine处理完请求后也会通过Connector将响应返回给客户端。
可以说Servlet容器处理请求是需要Connector进行调度和控制的Connector是Tomcat处理请求的主干因此Connector的配置和使用对Tomcat的性能有着重要的影响。这篇文章将从Connector入手讨论一些与Connector有关的重要问题包括NIO/BIO模式、线程池、连接数等。
根据协议的不同Connector可以分为HTTP Connector、AJP Connector等本文只讨论HTTP Connector。 一、Nio、Bio、APR
1、Connector的protocol
Connector在处理HTTP请求时会使用不同的protocol。不同的Tomcat版本支持的protocol不同其中最典型的protocol包括BIO、NIO和APRTomcat7中支持这3种Tomcat8增加了对NIO2的支持而到了Tomcat8.5和Tomcat9.0则去掉了对BIO的支持。
BIO是Blocking IO顾名思义是阻塞的IONIO是Non-blocking IO则是非阻塞的IO。而APR是Apache Portable Runtime是Apache可移植运行库利用本地库可以实现高可扩展性、高性能Apr是在Tomcat上运行高并发应用的首选模式但是需要安装apr、apr-utils、tomcat-native等包。点击查看 Tomcat Server 配置文件详解。 2、如何指定protocol
Connector使用哪种protocol可以通过connector元素中的protocol属性进行指定也可以使用默认值。
指定的protocol取值及对应的协议如下 HTTP/1.1默认值使用的协议与Tomcat版本有关 org.apache.coyote.http11.Http11ProtocolBIO org.apache.coyote.http11.Http11NioProtocolNIO org.apache.coyote.http11.Http11Nio2ProtocolNIO2 org.apache.coyote.http11.Http11AprProtocolAPR
如果没有指定protocol则使用默认值HTTP/1.1其含义如下在Tomcat7中自动选取使用BIO或APR如果找到APR需要的本地库则使用APR否则使用BIO在Tomcat8中自动选取使用NIO或APR如果找到APR需要的本地库则使用APR否则使用NIO。 3、BIO/NIO有何不同
无论是BIO还是NIOConnector处理请求的大致流程是一样的
在accept队列中接收连接当客户端向服务器发送请求时如果客户端与OS完成三次握手建立了连接则OS将该连接放入accept队列在连接中获取请求的数据生成request调用servlet容器处理请求返回response。为了便于后面的说明首先明确一下连接与请求的关系连接是TCP层面的传输层对应socket请求是HTTP层面的应用层必须依赖于TCP的连接实现一个TCP连接中可能传输多个HTTP请求。
在BIO实现的Connector中处理请求的主要实体是JIoEndpoint对象。JIoEndpoint维护了Acceptor和WorkerAcceptor接收socket然后从Worker线程池中找出空闲的线程处理socket如果worker线程池没有空闲线程则Acceptor将阻塞。其中Worker是Tomcat自带的线程池如果通过Executor配置了其他线程池原理与Worker类似。
在NIO实现的Connector中处理请求的主要实体是NIoEndpoint对象。NIoEndpoint中除了包含Acceptor和Worker外还是用了Poller处理流程如下图所示图片来源http://gearever.iteye.com/blog/1844203。 Acceptor接收socket后不是直接使用Worker中的线程处理请求而是先将请求发送给了Poller而Poller是实现NIO的关键。Acceptor向Poller发送请求通过队列实现使用了典型的生产者-消费者模式。在Poller中维护了一个Selector对象当Poller从队列中取出socket后注册到该Selector中然后通过遍历Selector找出其中可读的socket并使用Worker中的线程处理相应请求。与BIO类似Worker也可以被自定义的线程池代替。点击查看 Tomcat Server 配置文件详解。 通过上述过程可以看出在NIoEndpoint处理请求的过程中无论是Acceptor接收socket还是线程处理请求使用的仍然是阻塞方式但在“读取socket并交给Worker中的线程”的这个过程中使用非阻塞的NIO实现这是NIO模式与BIO模式的最主要区别其他区别对性能影响较小暂时略去不提。而这个区别在并发量较大的情形下可以带来Tomcat效率的显著提升 目前大多数HTTP请求使用的是长连接HTTP/1.1默认keep-alive为true而长连接意味着一个TCP的socket在当前请求结束后如果没有新的请求到来socket不会立马释放而是等timeout后再释放。如果使用BIO“读取socket并交给Worker中的线程”这个过程是阻塞的也就意味着在socket等待下一个请求或等待释放的过程中处理这个socket的工作线程会一直被占用无法释放因此Tomcat可以同时处理的socket数目不能超过最大线程数性能受到了极大限制。而使用NIO“读取socket并交给Worker中的线程”这个过程是非阻塞的当socket在等待下一个请求或等待释放时并不会占用工作线程因此Tomcat可以同时处理的socket数目远大于最大线程数并发性能大大提高。 二、3个参数acceptCount、maxConnections、maxThreads
再回顾一下Tomcat处理请求的过程在accept队列中接收连接当客户端向服务器发送请求时如果客户端与OS完成三次握手建立了连接则OS将该连接放入accept队列在连接中获取请求的数据生成request调用servlet容器处理请求返回response。
相对应的Connector中的几个参数功能如下
1、acceptCount
accept队列的长度当accept队列中连接的个数达到acceptCount时队列满进来的请求一律被拒绝。默认值是100。
2、maxConnections
Tomcat在任意时刻接收和处理的最大连接数。当Tomcat接收的连接数达到maxConnections时Acceptor线程不会读取accept队列中的连接这时accept队列中的线程会一直阻塞着直到Tomcat接收的连接数小于maxConnections。如果设置为-1则连接数不受限制。
默认值与连接器使用的协议有关NIO的默认值是10000APR/native的默认值是8192而BIO的默认值为maxThreads如果配置了Executor则默认值是Executor的maxThreads。
在windows下APR/native的maxConnections值会自动调整为设置值以下最大的1024的整数倍如设置为2000则最大值实际是1024。
3、maxThreads
请求处理线程的最大数量。默认值是200Tomcat7和8都是的。如果该Connector绑定了Executor这个值会被忽略因为该Connector将使用绑定的Executor而不是内置的线程池来执行任务。
maxThreads规定的是最大的线程数目并不是实际running的CPU数量实际上maxThreads的大小比CPU核心数量要大得多。这是因为处理请求的线程真正用于计算的时间可能很少大多数时间可能在阻塞如等待数据库返回数据、等待硬盘读写数据等。因此在某一时刻只有少数的线程真正的在使用物理CPU大多数线程都在等待因此线程数远大于物理核心数才是合理的。
换句话说Tomcat通过使用比CPU核心数量多得多的线程数可以使CPU忙碌起来大大提高CPU的利用率。
4、参数设置
1maxThreads的设置既与应用的特点有关也与服务器的CPU核心数量有关。通过前面介绍可以知道maxThreads数量应该远大于CPU核心数量而且CPU核心数越大maxThreads应该越大应用中CPU越不密集IO越密集maxThreads应该越大以便能够充分利用CPU。当然maxThreads的值并不是越大越好如果maxThreads过大那么CPU会花费大量的时间用于线程的切换整体效率会降低。
2maxConnections的设置与Tomcat的运行模式有关。如果tomcat使用的是BIO那么maxConnections的值应该与maxThreads一致如果tomcat使用的是NIO那么类似于Tomcat的默认值maxConnections值应该远大于maxThreads。
3通过前面的介绍可以知道虽然tomcat同时可以处理的连接数目是maxConnections但服务器中可以同时接收的连接数为maxConnectionsacceptCount 。acceptCount的设置与应用在连接过高情况下希望做出什么反应有关系。如果设置过大后面进入的请求等待时间会很长如果设置过小后面进入的请求立马返回connection refused。点击查看 Tomcat Server 配置文件详解。 三、线程池Executor
Executor元素代表Tomcat中的线程池可以由其他组件共享使用要使用该线程池组件需要通过executor属性指定该线程池。
Executor是Service元素的内嵌元素。一般来说使用线程池的是Connector组件为了使Connector能使用线程池Executor元素应该放在Connector前面。Executor与Connector的配置举例如下 Executor nametomcatThreadPool namePrefix catalina-exec- maxThreads150 minSpareThreads4 / Connector executortomcatThreadPool port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 acceptCount1000 / Executor的主要属性包括 name该线程池的标记 maxThreads线程池中最大活跃线程数默认值200Tomcat7和8都是 minSpareThreads线程池中保持的最小线程数最小值是25 maxIdleTime线程空闲的最大时间当空闲超过该值时关闭线程除非线程数小于minSpareThreads单位是ms默认值600001分钟 daemon是否后台线程默认值true threadPriority线程优先级默认值5 namePrefix线程名字的前缀线程池中线程名字为namePrefix线程编号
四、查看当前状态
上面介绍了Tomcat连接数、线程数的概念以及如何设置下面说明如何查看服务器中的连接数和线程数。
查看服务器的状态大致分为两种方案1使用现成的工具2直接使用Linux的命令查看。
现成的工具如JDK自带的jconsole工具可以方便的查看线程信息此外还可以查看CPU、内存、类、JVM基本信息等Tomcat自带的manager收费工具New Relic等。下图是jconsole查看线程信息的界面 下面说一下如何通过Linux命令行查看服务器中的连接数和线程数。
1、连接数
假设Tomcat接收http请求的端口是8083则可以使用如下语句查看连接情况 netstat –nat | grep 8083 结果如下所示 可以看出有一个连接处于listen状态监听请求除此之外还有4个已经建立的连接ESTABLISHED和2个等待关闭的连接CLOSE_WAIT。 2、线程
ps命令可以查看进程状态如执行如下命令 ps –e | grep java 结果如下图 可以看到只打印了一个进程的信息27989是线程idjava是指执行的java命令。这是因为启动一个tomcat内部所有的工作都在这一个进程里完成包括主线程、垃圾回收线程、Acceptor线程、请求处理线程等等。
通过如下命令可以看到该进程内有多少个线程其中nlwp含义是number of light-weight process。 ps –o nlwp 27989 可以看到该进程内部有73个线程但是73并没有排除处于idle状态的线程。要想获得真正在running的线程数量可以通过以下语句完成 ps -eLo pid ,stat | grep 27989 | grep running | wc -l 其中ps -eLo pid ,stat可以找出所有线程并打印其所在的进程号和线程当前的状态两个grep命令分别筛选进程号和线程状态wc统计个数。其中ps -eLo pid ,stat | grep 27989输出的结果如下 图中只截图了部分结果Sl表示大多数线程都处于空闲状态。