一.Tomcat内存优化
1.JAVA_OPTS参数说明
Tomcat内存优化主要是对 tomcat 启动参数优化,咱们能够在 tomcat 的启动脚本 catalina.sh 中设置 JAVA_OPTS参数。javascript
服务器参数配置php

配置完成后可重启Tomcat ,经过如下命令进行查看配置是否生效:css
1. 首先查看Tomcat 进程号:html
ps -ef|grep java

咱们能够看到Tomcat 进程号是 12222 。前端
1. 查看是否配置生效:java
sudo jmap -heap 12222

咱们能够看到MaxHeapSize 等参数已经生效。linux
优化 server.xml
Tomcat的主配置文件,该文件中包含不少主要元素,好比Service、Connector、Host等,这些元素都会建立软件"对象"、排序及进程管道中设置的这些元素嵌套方,使咱们能够执行过滤、分组等工做。nginx
若是要对该文件作优化,咱们须要先了解该文件的结构!web
server.xml的结构图:shell

该文件描述了如何启动Tomcat Server
<Server>
<Listener />
<GlobaNamingResources>
</GlobaNamingResources
<Service>
<Connector />
<Engine>
<Logger />
<Realm />
<host>
<Logger />
<Context />
</host>
</Engine>
</Service>
</Server>
针对该文件,咱们须要优化的点有以下:
一、 maxThreads 链接数限制
maxThreads 是 Tomcat 所能接受最大链接数。通常设置不要超过8000以上,若是你的网站访问量很是大可能使用运行多个Tomcat实例的方法, 即,在一个服务器上启动多个tomcat而后作负载均衡处理。
这里还须要注意的一点是,tomcat 和 php 不一样。php能够按照cpu和内存的状况去配置链接数,上万很正常。而 java 还须要注意 jvm 的参数配置。若是不注意就会由于jvm参数太小而崩溃。
二、多虚拟主机
强烈建议不要使用 Tomcat 的虚拟主机,推荐每一个站点使用一个实例。即,能够启动多个 Tomcat,而不是启动一个 Tomcat 里面包含多个虚拟主机。由于 Tomcat是多线程,共享内存,任何一个虚拟主机中的应用崩溃,都会影响到全部应用程序。虽然采用多实例的方式会产生过多的开销,但至少保障了应用程序的隔离和安全。
三、压错传输
tomcat做为一个应用服务器,也是支持 gzip 压缩功能的。咱们能够在 server.xml 配置文件中的 Connector 节点中配置以下参数,来实现对指定资源类型进行压缩。
compression="on" # 打开压缩功能
compressionMinSize="50" # 启用压缩的输出内容大小,默认为2KB
noCompressionUserAgents="gozilla, traviata" # 对于如下的浏览器,不启用压缩
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" # 哪些资源类型须要压缩
提示:
Tomcat 的压缩是在客户端请求服务器对应资源后,从服务器端将资源文件压缩,再输出到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程 HTML、CSS、Javascript和Text,它能够节省40% 左右的流量。更为重要的是,它能够对动态生成的,包括CGI、PHP、JSP、ASP、Servlet,SHTML等输出的网页也能进行压缩,压缩效率也很高。可是, 压缩会增长 Tomcat 的负担,所以最好采用Nginx + Tomcat 或者 Apache + Tomcat 方式,将压缩的任务交由 Nginx/Apache 去作。
一旦启用了这个压缩功能后,咱们怎么来测试压缩是否有效呢?首先Tomcat是根据浏览器请求头中的accept-encoding来判断浏览器是否支持 压缩功能,若是这个值包含有gzip,就代表浏览器支持gzip压缩内容的浏览,因此咱们能够用httpclient来写一个这样的简单测试程序
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
public class HttpTester {
public static void main(String[] args) throws Exception{
HttpClient http = new HttpClient();
GetMethod get = new GetMethod("http://www.dlog.cn/js/prototype.js");
try{
get.addRequestHeader("accept-encoding", "gzip,deflate");
get.addRequestHeader("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; Maxthon 2.0)");
int er = http.executeMethod(get);
if(er==200){
System.out.println(get.getResponseContentLength());
String html = get.getResponseBodyAsString();
System.out.println(html);
System.out.println(html.getBytes().length);
}
}finally{
get.releaseConnection();
}
}
}
执行这个测试程序,看看它所输出的是什么内容,若是输出的是一些乱码,以及打印内容的长度远小于实际的长度,那么恭喜你,你的配置生效了,你会发现你网站的浏览速度比之前快多了。
四、管理AJP端口
AJP是为 Tomcat 与 HTTP 服务器之间通讯而定制的协议,能提供较高的通讯速度和效率。若是tomcat前端放的是apache的时候,会使用到AJP这个链接器。因为咱们公司前端是由nginx作的反向代理,所以不使用此链接器,所以须要注销掉该链接器。
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
五、更改关闭 Tomcat 实例的指令
server.xml中定义了能够直接关闭 Tomcat 实例的管理端口。咱们经过 telnet 链接上该端口以后,输入 SHUTDOWN (此为默认关闭指令)便可关闭 Tomcat 实例(注意,此时虽然实例关闭了,可是进程仍是存在的)。因为默认关闭 Tomcat 的端口和指令都很简单。默认端口为8005,指令为SHUTDOWN 。所以咱们须要将关闭指令修改复杂一点。
固然,在新版的 Tomcat 中该端口仅监听在127.0.0.1上,所以你们也没必要担忧。除非黑客登录到tomcat本机去执行关闭操做。
修改实例:
<Server port="8005" shutdow n="9SDKJ29jksjf23sjf0LSDF92JKS9DKkjsd">
六、更改 Tomcat 的服务监听端口
通常公司的 Tomcat 都是放在内网的,所以咱们针对 Tomcat 服务的监听地址都是内网地址。
修改实例:
<Connector port="8080" address="172.16.100.1" />
七、关闭war自动部署
默认 Tomcat 是开启了对war包的热部署的。为了防止被植入木马等恶意程序,所以咱们要关闭自动部署。
修改实例:
<Host name="localhost" appBase=""
unpackWARs="false" autoDeploy="false">
二.Tomcat并发优化
1.调整链接器connector的并发处理能力
在Tomcat 配置文件 server.xml 中的 <Connector ... /> 配置中
1.参数说明
maxThreads 客户请求最大线程数
minSpareThreads Tomcat初始化时建立的 socket 线程数
maxSpareThreads Tomcat链接器的最大空闲 socket 线程数
minProcessors:最小空闲链接线程数,用于提升系统处理性能,默认值为 10
maxProcessors:最大链接线程数,即:并发处理的最大请求数,默认值为 75
acceptCount:容许的最大链接数,应大于等于 maxProcessors ,默认值为 100
enableLookups:是否反查域名,取值为: true 或 false 。为了提升处理能力,应设置为 false
redirectPort 在须要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort 端口
acceptAccount 监听端口队列最大数,满了以后客户请求会被拒绝(不能小于maxSpareThreads )
connectionTimeout:网络链接超时,单位:毫秒。设置为 0 表示永不超时,这样设置有隐患的。一般可设置为30000 毫秒。
URIEncoding URL统一编码
其中和最大链接数相关的参数为maxProcessors 和 acceptCount 。若是要加大并发链接数,应同时加大这两个参数。
web server容许的最大链接数还受制于操做系统的内核参数设置,一般 Windows 是 2000 个左右, Linux 是1000 个左右。
2.Tomcat中的配置示例
<Connector port="9027"
protocol="HTTP/1.1"
maxHttpHeaderSize="8192"
maxThreads="1000"
minSpareThreads="100"
maxSpareThreads="1000"
minProcessors="100"
maxProcessors="1000"
enableLookups="false"
URIEncoding="utf-8"
acceptCount="1000"
redirectPort="8443"
disableUploadTimeout="true"/>
3.Tomcat缓存优化
tomcat的maxThreads、acceptCount(最大线程数、最大排队数)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="800" acceptCount="1000"/>
tomcate -->config --> server.xml
其中最后两个参数意义以下:
maxThreads:tomcat起动的最大线程数,即同时处理的任务个数,默认值为200
acceptCount:当tomcat起动的线程数达到最大时,接受排队的请求个数,默认值为100
这两个值如何起做用,请看下面三种状况
状况1:接受一个请求,此时tomcat起动的线程数没有到达maxThreads,tomcat会起动一个线程来处理此请求。
状况2:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,tomcat会把此请求放入等待队列,等待空闲线程。
状况3:接受一个请求,此时tomcat起动的线程数已经到达maxThreads,等待队列中的请求个数也达到了acceptCount,此时tomcat会直接拒绝这次请求,返回connection refused
maxThreads如何配置
通常的服务器操做都包括量方面:1计算(主要消耗cpu),2等待(io、数据库等)
第一种极端状况,若是咱们的操做是纯粹的计算,那么系统响应时间的主要限制就是cpu的运算能力,此时maxThreads应该尽可能设的小,下降同一时间内争抢cpu的线程个数,能够提升计算效率,提升系统的总体处理能力。
第二种极端状况,若是咱们的操做纯粹是IO或者数据库,那么响应时间的主要限制就变为等待外部资源,此时maxThreads应该尽可能设的大,这样才能提升同时处理请求的个数,从而提升系统总体的处理能力。此状况下由于tomcat同时处理的请求量会比较大,因此须要关注一下tomcat的虚拟机内存设置和linux的open file限制。
我在测试时遇到一个问题,maxThreads我设置的比较大好比3000,当服务的线程数大到必定程度时,通常是2000出头,单次请求的响应时间就会急剧的增长,
百思不得其解这是为何,四处寻求答案无果,最后我总结的缘由多是cpu在线程切换时消耗的时间随着线程数量的增长愈来愈大,
cpu把大多数时间都用来在这2000多个线程直接切换上了,固然cpu就没有时间来处理咱们的程序了。
之前一直简单的认为多线程=高效率。。其实多线程自己并不能提升cpu效率,线程过多反而会下降cpu效率。
当cpu核心数<线程数时,cpu就须要在多个线程直接来回切换,以保证每一个线程都会得到cpu时间,即一般咱们说的并发执行。
因此maxThreads的配置绝对不是越大越好。
现实应用中,咱们的操做都会包含以上两种类型(计算、等待),因此maxThreads的配置并无一个最优值,必定要根据具体状况来配置。
最好的作法是:在不断测试的基础上,不断调整、优化,才能获得最合理的配置。
acceptCount的配置,我通常是设置的跟maxThreads同样大,这个值应该是主要根据应用的访问峰值与平均值来权衡配置的。
若是设的较小,能够保证接受的请求较快相应,可是超出的请求可能就直接被拒绝
若是设的较大,可能就会出现大量的请求超时的状况,由于咱们系统的处理能力是必定的。
提示
不少作过php运维的朋友在这里会犯一个大错误,php优化服务器一般怎作法是安装cpu以及内存的状况配置链接数,链接数过万都很正常,但java不一样jvm配置要很是当心,稍有差错就会崩溃。
maxThreads 配置要结合 JVM -Xmx 参数调整,也就是要考虑内存开销。
在线上环境中咱们是采用了tomcat做为Web服务器,它的处理性能直接关系到用户体验,在平时的工做和学习中,概括出如下七种调优经验。
1. 服务器资源
服务器所能提供CPU、内存、硬盘的性能对处理能力有决定性影响。
(1) 对于高并发状况下会有大量的运算,那么CPU的速度会直接影响处处理速度。
(2) 内存在大量数据处理的状况下,将会有较大的内存容量需求,能够用-Xmx -Xms -XX:MaxPermSize等参数对内存不一样功能块进行划分。咱们以前就遇到过内存分配不足,致使虚拟机一直处于full GC,从而致使处理能力严重降低。
(3) 硬盘主要问题就是读写性能,当大量文件进行读写时,磁盘极容易成为性能瓶颈。最好的办法仍是利用下面提到的缓存。
2. 利用缓存和压缩
对于静态页面最好是可以缓存起来,这样就没必要每次从磁盘上读。这里咱们采用了Nginx做为缓存服务器,将图片、css、js文件都进行了缓存,有效的减小了后端tomcat的访问。
另外,为了能加快网络传输速度,开启gzip压缩也是必不可少的。但考虑到tomcat已经须要处理不少东西了,因此把这个压缩的工做就交给前端的Nginx来完成。能够参考以前写的《利用nginx加速web访问》。
除了文本能够用gzip压缩,其实不少图片也能够用图像处理工具预先进行压缩,找到一个平衡点可让画质损失很小而文件能够减少不少。曾经我就见过一个图片从300多kb压缩到几十kb,本身几乎看不出来区别。
3. 采用集群
单个服务器性能老是有限的,最好的办法天然是实现横向扩展,那么组建tomcat集群是有效提高性能的手段。咱们仍是采用了Nginx来做为请求分流的服务器,后端多个tomcat共享session来协同工做。能够参考以前写的《利用nginx+tomcat+memcached组建web服务器负载均衡》。
4. 优化tomcat参数
这里以tomcat7的参数配置为例,须要修改conf/server.xml文件,主要是优化链接配置,关闭客户端dns查询。
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="500"
minSpareThreads="20"
acceptCount="100"
disableUploadTimeout="true"
enableLookups="false"
URIEncoding="UTF-8" />
5. 改用APR库
tomcat默认采用的BIO模型,在几百并发下性能会有很严重的降低。tomcat自带还有NIO的模型,另外也能够调用APR的库来实现操做系统级别控制。
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
修改成:
<Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol " connectionTimeout="20000" redirectPort="8443" />
NIO模型是内置的,调用很方便,只须要将上面配置文件中protocol修改为org.apache.coyote.http11.Http11NioProtocol,重启便可生效。上面配置我已经改过了,默认的是HTTP/1.1。
APR则须要安装第三方库,在高并发下会让性能有明显提高。具体安装办法能够参考http://www.cnblogs.com/huangjingzhou/articles/2097241.html。安装完成后重启便可生效。如使用默认protocal就是apr,但最好把将protocol修改为org.apache.coyote.http11.Http11AprProtocol,会更加明确。
在官方找到一个表格详细说明了这三种方式的区别:
|
Java Blocking Connector |
Java Nio Blocking Connector |
APR/native Connector |
|
BIO |
NIO |
APR |
Classname |
AjpProtocol |
AjpNioProtocol |
AjpAprProtocol |
Tomcat Version |
3.x onwards |
7.x onwards |
5.5.x onwards |
Support Polling |
NO |
YES |
YES |
Polling Size |
N/A |
maxConnections |
maxConnections |
Read Request Headers |
Blocking |
Sim Blocking |
Blocking |
Read Request Body |
Blocking |
Sim Blocking |
Blocking |
Write Response |
Blocking |
Sim Blocking |
Blocking |
Wait for next Request |
Blocking |
Non Blocking |
Non Blocking |
Max Connections |
maxConnections |
maxConnections |
maxConnections |
6. 优化网络
Joel也明确提出了优化网卡驱动能够有效提高性能,这个对于集群环境工做的时候尤其重要。因为咱们采用了linux服务器,因此优化内核参数也是一个很是重要的工做。给一个参考的优化参数:
1. 修改/etc/sysctl.cnf文件,在最后追加以下内容:
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000 net.ipv4.tcp_max_orphans = 3276800 net.ipv4.tcp_max_syn_backlog = 65536
2. 保存退出,执行sysctl -p生效
7. 让测试说话
优化系统最忌讳的就是只调优不测试,有时不适当的优化反而会让性能更低。以上全部的优化方法都要在本地进行性能测试事后再不断调整参数,这样最终才能达到最佳的优化效果。
补充Bio、Nio、Apr模式的测试结果:
对于这几种模式,我用ab命令模拟1000并发测试10000词,测试结果比较意外,为了确认结果,我每种方式反复测试了10屡次,而且在两个服务器上都测试了一遍。结果发现Bio和Nio性能差异很是微弱,难怪默认竟然仍是Bio。可是采用apr,链接创建的速度会有50%~100%的提高。直接调用操做系统层果真神速啊,这里强烈推荐apr方式!
Tomcat从5.5版本开始,支持如下四种Connector的配置分别为:
<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443"/>
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000"
redirectPort="8443"/>
<Connector executor="tomcatThreadPool"
port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector executor="tomcatThreadPool"
port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443" />
咱们姑且把上面四种Connector按照顺序命名为 NIO, HTTP, POOL, NIOP
为了避免让其余因素影响测试结果,咱们只对一个很简单的jsp页面进行测试,这个页面仅仅是输出一个Hello World。假设地址是 http://tomcat1/test.jsp
咱们依次对四种Connector进行测试,测试的客户端在另一台机器上用ab命令来完成,测试命令为: ab -c 900 -n 2000 http://tomcat1/test.jsp ,最终的测试结果以下表所示(单位:平均每秒处理的请求数):
NIO HTTP POOL NIOP
281 |
65 |
208 |
365 |
666 |
66 |
110 |
398 |
692 |
65 |
66 |
263 |
256 |
63 |
94 |
459 |
440 |
67 |
145 |
363 |
由这五组数据不难看出,HTTP的性能是很稳定,可是也是最差的,而这种方式就是Tomcat的默认配置。NIO方式波动很大,但没有低于280 的,NIOP是在NIO的基础上加入线程池,多是程序处理更复杂了,所以性能不见得比NIO强;而POOL方式则波动很大,测试期间和HTTP方式同样,不时有停滞。
因为linux的内核默认限制了最大打开文件数目是1024,所以这次并发数控制在900。
尽管这一个结果在实际的网站中由于各方面因素致使,可能差异没这么大,例如受限于数据库的性能等等的问题。但对咱们在部署网站应用时仍是具备参考价值的。
1. JVM