Tomcat笔记(二) tomcat优化

对于tomcat的优化,主要是从两个方面入手,第一是,tomcat自身的配置,另一个是tomcat所运行的jvm虚拟机的。

一. Tomcat的server.xml配置分析

        Tomcat的Connector是其接收HTTP请求的关键模块, 可以通过它来指定IO处理模式, 指定处理该Connector接收到的请求的线程数等。需要在 tomcat安装目录的conf目录下server.xml 文件的节点中进行配置。

1.1 Executor线程池配置分析

        Executor与Connector同级, 多个Connector可以使用同一个线程池来处理请求.

(1) 默认线程池配置:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="150" minSpareThreads="4"/> 

(2) 自定义线程池示例:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="200" minSpareThreads="10" maxIdleTime="600000"

prestartminSpareThreads="true" maxQueueSize="100"  />   

(3) 线程池Executor 参数说明:

name: 线程池名称.

namePrefix: 创建的每个线程的名称前缀, 单独的线程名称为 namePrefix + threadNumber.

maxThreads: 线程池中最大并发线程数, 默认值为200, 一般建议设置400~ 800 , 要根据服务器配置和业务需求而定.

minSpareThreads: 最小活跃线程数, 也就是核心线程数, 不会被销毁, 会一直存在.

prestartminSpareThreads: 是否在启动程序时就生成minSpareThreads个线程, 默认为false, 即不启动. 若不设置为true, 则minSpareThreads的设置就不起作用了.

maxIdleTime: 线程最大空闲时间, 超过该时间后, 空闲线程会被销毁, 默认值为6000, 单位为毫秒.

maxQueueSize: 最大的等待队列数, 超过则拒绝请求. 默认值为int类型的最大值(Integer.MAX_VALUE), 等同于无限大. 一般不作修改, 避免发生部分请求未能被处理的情况.

threadPriority: 线程池中线程的优先级, 默认值为5, 取值范围: 1 ~ 10.

className:线程池的实现类, 默认实现类为 org.apache.catalina.core.StandardThreadExecutor.要自定义线程池就需要实现 org.apache.catalina.Executor 接口.

  1. maxThreads分析:

       一般的服务器操作都包括两方面:1计算(主要消耗cpu),2等待(io、数据库等)。

       第一种极端情况,如果我们的操作是纯粹的计算,那么系统响应时间的主要限制就是cpu的运算能力,此时maxThreads应该尽量设的小,降低同一时间内争抢cpu的线程个数,可以提高计算效率,提高系统的整体处理能力。

       第二种极端情况,如果我们的操作纯粹是IO或者数据库,那么响应时间的主要限制就变为等待外部资源,此时maxThreads应该尽量设的大,这样才能提高同时处理请求的个数,从而提高系统整体的处理能力。此情况下因为tomcat同时处理的请求量会比较大,所以需要关注一下tomcat的虚拟机内存设置。

       当cpu核心数<线程数时,cpu就需要在多个线程直接来回切换,以保证每个线程都会获得cpu时间,即通常我们说的并发执行。cpu在线程切换时消耗的时间随着线程数量的增加越来越大;如果线程数过大时,cpu会把很多时间用在线程切换上,就没有时间来处理我们的程序了,这样就降低了cpu的效率。所以maxThreads的配置绝对不是越大越好。

       现实应用中,maxThreads的配置并没有一个最优值,最好的做法是:在不断测试的基础上,不断调整、优化,才能得到最合理的配置。

1.2 Connector连接池配置分析(引入了线程池)

Connector是Tomcat接收请求的入口, 每个Connector都有自己专属的监听端口。

web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。

默认:   

<Connector executor="tomcatThreadPool"

             port="8080" protocol="HTTP/1.1"

             connectionTimeout="20000"

             redirectPort="8443" />

自定义demo:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"  
        connectionTimeout="20000"  
        redirectPort="8443"   
        executor="tomcatThreadPool"  
        enableLookups="false"   
        acceptCount="100"   
        maxPostSize="10485760"   
        compression="on"   
        disableUploadTimeout="true"   
        compressionMinSize="2048"   
        noCompressionUserAgents="gozilla, traviata"   
        acceptorThreadCount="2"   
        compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript"   
        URIEncoding="utf-8"/>  
 

连接池Connector参数说明:

redirectPort="8443" 是基于SSL的端口, 在需要基于安全通道的场合, 比如当客户端的请求协议是HTTPS时, 将该请求转发到此端口。

executor: 连接器使用的线程池名称。

protocol:连接器使用的传输方式。  Tomcat 8 设置 nio2 更好:org.apache.coyote.http11.Http11Nio2Protocol 。Tomcat 6、7 设置 nio 更好:org.apache.coyote.http11.Http11NioProtocol 。
注:
      每个web客户端请求对于服务器端来说就一个单独的线程,客户端的请求数量增多将会导致线程数就上去了,CPU就忙着           跟线程切换。而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由线程池来处理堵塞在pipe     或者队列里的请求.这样的话,只要OS可以接受TCP的连接,web服务器就可以处理该请求。大大提高了web服务器的可伸缩性。

minSpareThreads="25" 是Tomcat连接器的最小空闲Socket线程数, 默认值为25. 如果当前没有空闲线程, 且没有超过。maxThreads, 将一次性创建的空闲线程数量. Tomcat初始化时创建的线程数量也是此值。

maxSpareThreads="75" 是最大空闲线程数, 一旦创建的线程超过此值, Tomcat就会关闭不再需要的Socket线程, 默认值为50. 线程数可以大致用 "同时在线用户数、用户每秒操作次数、系统平均操作时间" 来计算。

keepAliveTimeout="6000" 是下次请求到来之前, Tomcat保持该连接6000ms。

maxKeepAliveRequests="10" # 该连接最大支持的请求数, 超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端). 1表示禁用长连接, -1表示不限制连接个数, 默认为100, 一般设置在100~200之间。

enableLookups="false" # 是否支持反查域名(即DNS解析), 默认为true. 为提高处理能力, 应设置为false(即:禁用DNS查询)。

disableUploadTimeout="true" # 上传时是否启用超时机制, 若为true, 则禁用上传超时。

connectionTimeout="20000" # 网络连接超时时间, 默认值为20000ms, 设置为0表示永不超时 —— 存在隐患. 通常可设置为30000ms。

URIEncoding="UTF-8" # 指定Tomcat容器的URL编码格式。

maxHttpHeaderSize="8192" # HTTP请求头信息的最大程度, 超过此长度的部分不予处理. 一般设置为8K即可。

maxPostSize="10485760" # 指定POST请求的内容大小, 单位为Byte, 默认大小为2097152(2MB), 10485760为10M. 如果要禁用限制, 可设置为-1。

acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认设置 100 。
acceptorThreadCount: 用于接收连接的线程的数量,默认值是1。一般这个指需要改动的时候是因为该服务器是一个多核CPU,如果是多核 CPU 一般配置为 2。
compression:传输时是压缩。
compressionMinSize:压缩的大小。
noCompressionUserAgents:不启用压缩的浏览器。
提示:
        压缩会增加Tomcat负担,最好采用Nginx + Tomcat 或者 Apache + Tomcat 方式,压缩交由Nginx/Apache 去做。 
        Tomcat 的压缩是在客户端请求服务器对应资源后,从服务器端将资源文件压缩,再输出到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的 浏览过程 HTML、CSS、Javascript和Text,它可以节省40% 左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP、JSP、ASP、Servlet,SHTML等输出的网页也能进行压缩,压缩效率也很高。

 

不要混淆了 异步servlet和非阻塞connector,它们一个是Executor,一个是Connector,两者的工作阶段不同。 

Servlet:一个Servelet,就是一个线程一次的执行过程。比如响应doGet(),这个是在一个独立的线程中完成的。

当connector建立连接后,服务器会分配一个线程(可能是从线程池)去服务这个连接,即执行doGet等方法,执行完,回收线程。显然这一步是一个同步的过程,tomcat对应的是Executor。

Connector和Servlet(Executor)可以不共用一个线程,一个维护连接,Executor用独立的线程来服务,tomcat采用的就是这种方式。

tomcat使用线程池,线程最多增加到maxThreads ,如果还有请求进来,那么这些请求就会wait在connector上,如果connector上wait的请求超出了acceptCount ,那么服务器就返回 "connection refused"拒绝连接错误。 

1.3 Tomcat Connector三种运行模式(BIO, NIO, APR)

Tomcat Connector 是请求接收环节与请求处理环节的连接器,具体点说,就是将接收到的请求传递给Tomcat WEB容器进行处理。Tomcat可以处理的不同协议的请求,例如HTTP协议、AJP协议。其中AJP是Tomcat与其他Web Server(例如Apache Server、IIS等)连接使用的协议。对于HTTP协议,根据处理Socket中IO的方式的不同,又可以分为BIO、NIO、APR方式。

1.3.1 Tomcat Connector默认配置

外部ip访问连接到服务器,会有很多connection(连接),建立、维护、管理这些连接,这就是connector要做的事情。

 

(一)BIO:(blocking I/O)是指阻塞式I/O操作,Tomcat7或以下,在Linux系统中默认就是以bio模式运行的。一个线程处理一个请求。缺点:并发量高时,线程数较多,浪费资源。

(二)NIO/NIO2:(non-blocking I/O)是非阻塞I/O操作。NIO是一个基于缓冲区并能提供非阻塞I/O操作的Java API,它拥有比传统的BIO更好的并发运行性能。利用Java的异步IO处理,可以通过少量的线程处理大量的请求。Tomcat8在Linux系统中默认使用这种方式

(三)APR:(Apache Portable Runtime),即Apache可移植运行库,APR的使命是创建和维护一套软件库,以便在不同操作系统(Windows、Linux等)底层实现的基础上提供统一的API,是从操作系统层面解决IO阻塞问题、异步IO问题,大幅度提高服务器的并发处理性能,也是Tomcat生产环境运行的首选方式在apr模式下。Linux如果安装了apr和native,Tomcat直接启动就支持APR。

       在产品环境中,特别是直接使用Tomcat做WEB服务器的时候,应该使用Tomcat Native来提高其性能。要测APR给tomcat带来的好处最好的方法是在慢速网络上(模拟Internet),将Tomcat线程数开到300以上的水平,然后模拟一大堆并发请求。

       如果不配APR,基本上300个线程狠快就会用满,以后的请求就只好等待。但是配上APR之后,并发的线程数量明显下降,从原来的300可能会马上下降到只有几十,新的请求会毫无阻塞的进来。

       在局域网环境测,就算是400个并发,也是一瞬间就处理/传输完毕,但是在真实的Internet环境下,页面处理时间只占0.1%都不到,绝大部分时间都用来页面传输。如果不用APR,一个线程同一时间只能处理一个用户,势必会造成阻塞。所以生产环境下用APR是非常必要的。

1.4 AJP协议

AJP(Apache JServ Protocol)是定向包协议。WEB服务器和Servlet容器通过TCP连接来交互;为了节省Socket创建的昂贵代价,WEB服务器会尝试维护一个永久TCP连接到servlet容器,并且在多个请求和响应周期过程会重用连接。

1.4.1 Tomcat的server.xml中的AJP和HTTP连接器区别:

HTTP协议:连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。  

AJP协议:连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。

分析了这么一堆,tomcat8自身的配置优化总结如下:

1 禁用AJP服务

tomcat8默认状态下会启用AJP服务,并且占用8009端口。

AJP是为Tomcat与HTTP服务器之间通信而定制的协议,能提供较高的通信速度和效率。如果tomcat前端放的是apache的时候,会使用到AJP这个连接器。 默认是开启的。如果不使用apache,注释该连接器。我们一般是使用Nginx+tomcat的架构,所以用不着AJP协议,修改conf下的server.xml文件,将AJP服务禁用掉即可。

禁用DNS查询

当web应用程序向要记录客户端的信息时,它也会记录客户端的IP地址或者通过域名服务器查找机器名 转换为IP地址。DNS查询需要占用网络,并且包括可能从很多很远的服务器或者不起作用的服务器上去获取对应的IP的过程,这样会消耗一定的时间。

修改server.xml文件中的Connector元素,修改属性enableLookups参数值: enableLookups="false"。

如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址。

3 启用线程池

线程池中的最大线程数,初始化的核心线程数,队列长度这些需要结合项目去设置,通过多次的调试找出更加适合的参数。

4 tomcat8以下的Connector的运行模式为使用nio,tomcat8及以上使用nio2。

通过以上方式可以显著提升应用的吞吐量并降低平均响应时间。

 

二. Tomcat使用内存优化(调整jvm参数)

tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,需要调大。Tomcat内存优化主要是对tomcat启动参数优化,可以新增或者修改在文件tomcat安装目录下的/bin/catalina.sh 中的JAVA_OPTS参数。

JAVA_OPTS参数说明:

    -server  启用jdk 的 server 版;  

    -Xms    java虚拟机初始化时的最小堆内存;  

    -Xmx   java虚拟机可使用的最大堆内存;  

 

JAVA_OPTS='-server -Xms【初始化堆内存大小】 -Xmx【可以使用的最大堆内存】'

需要把这个两个参数值调大。例如:

JAVA_OPTS='-server -Xms256m -Xmx512m'

表示初始化堆内存为256MB,可以使用的最大堆内存为512MB。

       应用程序在大负载的情况下会急剧地占用更多的内存,一般使用数据量较大的应用程序会使用持久对象,内存使用有可能迅速地增长。当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃。此时这两个参数就是显得非常重要,如果虚拟机启动时设置使用的内存比较小而在这种情况下有许多对象进行初始化,虚拟机就必须重复地增加内存来满足使用。由于这种原因,我们一般把-Xms和-Xmx设为一样大或者相差不大,而堆的最大值受限于系统使用的物理内存。

本文参考了诸多资料,并加入了个人的理解和经验,在此做下总结,欢迎交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值