常规tomcat拥有三种运行模式:
bio:默认的模式,性能非常的低下,没有经过任何优化的处理和支持;
nio:nio(new I/O),是Java SE 1.4及后续版本提供的一种新的I/O操作方式(即java.nio包及其子包)。Java nio是一个基于缓冲区、并能提供非阻塞I/O操作的Java API,因此nio也被看成是non-blocking I/O的缩写。它拥有比传统I/O操作更好的并发运行性能;
apr:安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能。
怎么查看自己当前的运行模式?
1、进入tomcat文件夹根目录下的conf文件夹,找到tomcat-users.xml文件,也就是/tomcat/conf/tomcat-users.xml 文件,修改。找到最下面一行</tomcat-users>标签,在它的上面插入如下
<role rolename="manager"/> <role rolename="manager-gui"/> <role rolename="admin"/> <role rolename="admin-gui"/> <user username="createdpro" password="123456789" roles="admin-gui,admin,manager-gui,manager"/>
保存退出
2、这样我们就创建了一个用户名为createdpro,密码为123456789的tomcat用户,接下来启动tomcat,在浏览器的地址栏输入127.0.0.1:8080(如果有修改过请按修改过的路径及端口号进行访问),可以看到经典的tomcat大猫的页面,在页面的右侧找到Server Status按钮,点击后使用刚刚设置的账号密码登录——
在这里面依次列出了:服务器信息->JVM虚拟机信息->ajp协议状态->http协议状态
这里后面我们可以看到 http-bio-8080 ,说明我们当前的运行模式是属于bio的模式(如果是nio,也需要进行修改)。
怎么修改为nio的运行模式?
1、启动NIO模式方法:修改server.xml里的 <Connector port="8080" …… /> 节点,将protocol中的 HTTP/1.1 修改为org.apache.coyote.http11.Http11NioProtocol
修改完成!
二、tomcat线程池优化
线程池开启(为什么要使用线程池可参考百度谷歌)
1、tomcat默认关闭线程池,我们需要手动打开并可以进行一些配置。
2、编辑 /tomcat/conf/server.xml 文件,找到 <Service name="Catalina"> 节点,再节点的下面我们可以看到:
但是这段标签被注释掉了……(你问为啥要注释掉?开发的时候你要500W的并发有卵用?还很占用开发资源)所以我们现在要打开注释(新世界的大门):
这样,我们就启用了tomcat的线程池功能?不!当然没那么容易(阴险笑~)
我们还要在 <Connector port="8080" …… /> 这个节点中加上这个以指定线程池:executor="tomcatThreadPool"
这个参数等同于线程池标签中的name
3、标签中的部分属性参数配置解释:
name 线程池的名字,如启用线程池,需要在 <Connector port="8080" …… /> 中配置
maxThreads 最大线程数,默认为200
minSpareThreads 最小活跃线程数,默认25
maxIdleTime 空闲线程等待时间,默认 60000 ms(1 min)
maxQueueSize 最大的等待队列数(超出线程池数量的请求会进入排队),超过则请求拒绝,默认值为 java Integer 的最大值 2147483647(暗指不限)
prestartminSpareThreads 是否需要在启动时就生成minSpareThreads这个数量的线程,默认是false
还有一些参数作者认为不重要,如有特殊需求可查阅tomcat官方文档(文末)。
三、<Connector />连接器优化
连接器部分参数解释
启动本机的tomcat后访问 http://127.0.0.1:8080/docs 即可访问tomcat自带的本地文档。
asyncTimeout:异步请求以毫秒为单位默认超时时间,如果不指定该参数,将被缺省设置为 10000 ms;
maxHeaderCount:容器允许的请求头最大数目,该值默认为100,如果请求头数超过该值tomcat会报异常,笔者在这吃过亏;
maxParameterCount:对容器所能解析的最大参数(键值对)的数量进行限制(GET + POST),参数值对、超出的部分会被忽略掉,值小于零表示不限制,默认为10000;
maxPostSize:容器限制的由FORM URL提交POST参数的最大长度(byte),该值的默认值为 2097152 byte(2M)。该长度包括提交的媒体文件(图片、文件等);
port:TCP端口号,连接器利用该端口号创建一个服务套接字,并等待传入的连接。你的操作系统将只允许一个服务器应用程序在一个特定的IP地址侦听特定的端口号。如果使用特殊值0,则Tomcat将为连接器随机选择一个空闲的端口。这通常只用在嵌入式和测试应用程序;
protocol:设置协议来处理传入流量。默认值是 HTTP/1.1 ,将使用自动切换机制来选择阻塞的基于Java的连接器或 APR/native 为基础的连接器。如果PATH(Windows)或LD_LIBRARY_PATH(Unix)的环境变量包含在Tomcat的本地库里,APR/native 将会被使用,如果无法在本地库中找到,将会使用阻塞式的基于Java的连接器。需要注意的是如果使用HTTPS,常规的Java连接器和 APR/native 的配置将完全不同。如果明确自己的协议,应该不依靠上述自动切换机制,应采用以下值:
org.apache.coyote.http11.Http11Protocol - 阻塞式的Java连接器
org.apache.coyote.http11.Http11NioProtocol - 不阻塞的Java连接器
org.apache.coyote.http11.Http11AprProtocol - APR/native连接器
HTTP与HTTPS在使用Java连接器时配置是相同的,APR连接器则需要特定的配置,详见APR文档;
proxyName:如果这个链接正在使用的代理服务器配置,配置该属性指定的服务器名称,可以调用 request.getServerName() 返回。有关更多信息请参见代理支持;
proxyPort:如果这个链接正在使用的代理服务器配置,配置该属性指定的服务器端口,可以调用 request.getServerPort() 返回。有关更多信息请参见代理支持;
redirectPort:如果该链接器支持非SSL请求,并且接收到的请求为满足安全约束需要SSL传输,Catalina将自动将请求重定向到指定的端口号;
scheme:将该属性设置为你想调用 request.getScheme() 返回的协议的名称。例如,对于SSL连接器,你要讲此属性设置为“HTTPS”。默认值是“HTTP”;
URIEncoding:这将指定使用的字符编码来解码URI字符。默认使用ISO-8859-1;
可以自行进行按需配置,这里只展示部分文档,完整版请前往tomcat文档(文末附链接)。
贴一个例子:
<connector executor="tomcatThreadPool" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" enableLookups="false" maxPostSize="10485760" URIEncoding="UTF-8" acceptCount="100" acceptorThreadCount="2" disableUploadTimeout="true" maxConnections="10000" SSLEnabled="false"/>
四、禁用AJP协议
AJP(Apache JServ Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过TCP连接和SERVLET容器连接。AJP是定向包协议。因为性能原因,使用二进制格式来传输可读性文本。WEB服务器通过TCP连接和SERVLET容器连接。为了减少进程生成socket的花费,WEB服务器和SERVLET容器之间尝试保持持久性的TCP连接,对多个请求/回复循环重用一个连接。一旦连接分配给一个特定的请求,在请求处理循环结束之前不会再分配。换句话说,在连接上,请求不是多元的。这个使连接两端的编码变得容易,虽然这导致在一时刻会有很多连接。——《百度百科》
如果换成人话说,就是Tomcat服务器本身对静态资源的处理性能非常的低下,所以我们通常会采用一些能够更好的对静态资源处理的例如Apache、nginx服务器等做html、css、js的单独加载。
AJP协议将会在请求时自动将静态文件请求直接转发给Apache服务器,由于AJP是一个二进制的TCP传输协议,相比HTTP这种纯文本的协议来说,效率和性能更高,以此来提高请求处理效率。
但是,如果你没用使用Apache服务器,他就没卵用了,因为支持AJP协议的服务器特别少。比如目前大火的nginx,就不支持~~~
所以——下面是禁用的方法:
1、编辑 /tomcat/conf/server.xml 找到 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> ,把他注释掉(ps:可以删但没必要)。
2、注释方法:<!-- 被注释掉的内容 -->
五、tomcat的JVM参数优化
如何优化?
(举例)修改文件:bin/catalina.sh
(举例)第一行加入:JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:NewRatio=2 -XX:MaxTenuringThreshold=50 -XX:+DisableExplicitGC"
参数说明:
1、 file.encoding 默认文件编码
2、 -Xmx1024m 设置JVM最大可用内存为1024MB
3、 -Xms1024m 设置JVM最小内存为1024m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
4、 -XX:NewSize 设置年轻代大小
5、 XX:MaxNewSize 设置最大的年轻代大小
6、 -XX:PermSize 设置永久代大小
7、 -XX:MaxPermSize 设置最大永久代大小
8、 -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与终身代的比值(除去永久代)。设置为4,则年轻代与终身代所占比值为1:4,年轻代占整个堆栈的1/5
9、 -XX:MaxTenuringThreshold=0:设置垃圾最大年龄,默认为:15。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
10、-XX:+DisableExplicitGC这个将会忽略手动调用GC的代码使得 System.gc()的调用就会变成一个空调用,完全不会触发任何GC
以下是优化实例:
(实例)linux:
修改tomcat/bin/catalina.sh文件参数(第一行)
JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=1024m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC"
(实例)windows:
修改tomcat/bin/catalina.bat文件设置参数(第一行)
set JAVA_OPTS=-Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=1024m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC
写在最后:
1、性能调优要做到有的放矢,根据实际业务系统的特点,以一定时间的JVM日志记录为依据,进行有针对性的调整、比较和观察。
2、性能调优是个无止境的过程,要综合权衡调优成本和更换硬件成本的大小,使用最经济的手段达到最好的效果。
3、性能调优不仅仅包括JVM的调优,还有服务器硬件配置、操作系统参数、中间件线程池、数据库连接池、数据库本身参数以及具体的数据库表、索引、分区等的调整和优化。
4、通过特定工具检查代码中存在的性能问题并加以修正是一种比较经济快捷的调优方法。
tomcat官方文档:http://tomcat.apache.org/tomcat-7.0-doc/index.html
【转载请注明来源】