作为运维,避免不了与tomcat打交道,然而作者发现网络上关于tomcat配置和调优安全的文章非常散,通过参考各位大神的相关技术文档,根据作者对tomcat的运维经验,总结了一些tomcat的基础运维注意事项,希望对广大技术兄弟们有些帮助。
本篇文章只是对tomcat模板的基础调优,除了部署tomcat的各系统环境和配置,影响tomcat并发和性能的另一大重要因素,就是java的代码工程,而如何在生产中优化java工程,这个就需要运维与开发共同配合,尤其是运维需要有开发与运维是同一个团队的意识,只有双方配合默契才能发挥最大战力,要知道一个人的力量永远是有限的,只有团队合作才能爆发出真正力量!
而包含了Java工程的整体优化就设计到整体的架构优化,这个更加是一个细致而有趣的过程,也是运维通向架构师的一个必经之路!
1功能优化
1.1硬件资源对tomcat的影响
作者实测,在阿里云的不同区域部署相同系统应用配置的tomcat,在压测时会出现吞吐量差异达到1/4,经过对比发现,两个区域的cpu频率2.2GHz和2.6Ghz。系统硬件性能直接影响tomcat的并发量,起决定作用的是CPU和MEM,CPU运行速度提升,会带来tomcat响应时间的缩短,mem大小决定工程需要内存的大小和工程的并发数量。
1.2Java虚拟机调优
1.2.1JDK版本选择
如果新手请选择SUN的JVM,在满足项目需要的前提下,尽量选用版本较高的JVM,一般来说高版本产品在速度和效率上比低版本会有改进。JDK1.4比JDK1.3性能提高了近10%-20%,JDK1.5比JDK1.4性能提高25%-75%。因此对性能要求较高的情况推荐使用JDK1.6。
这里需要补充的是,各位在打算升级JVM时,一定要先让开发先试用高版本的JVM,调试高版本JVM对工程的影响,经过测试后逐步部署到测试环境,经过一定时间的验证,发现没有问题后再谨慎的更换到生产。JVM版本不一致,很容易出现各类异常,对待生产,谨慎永远是第一原则!
JVM调优参见:http://vekergu.blog.51cto.com/9966832/1626733
1.2.2JDK参数优化
Tomcat内存优化主要是对tomcat启动参数优化,我们可以在tomcat的启动脚本catalina.sh中设置JAVA_OPTS参数。
1.JAVA_OPTS参数说明
-server 启用jdk 的 server 版;
-Xms java虚拟机初始化时的最小内存;
-Xmx java虚拟机可使用的最大内存;
-XX:PermSize 内存永久保留区域
-XX:MaxPermSize 内存最大永久保留区域
-Xms=-Xmx=服务器内存*70%,如部署tomcat,jboss在同一台服务器-Xms=-Xmx=服务器内存*80%*1/4,现公司服务器内存一般都可以加到最大4G,所以可以采取以下配置,把以下参数添加到catalina.sh里面,
JAVA_OPTS='-Xms1024m -Xmx4096m -XX:PermSize=256M -XX:MaxNewSize=256m-XX:MaxPermSize=256m'
#-Xmx6000m :设置JVM最大可用内存为6000MB
#-Xms6000m :设置JVM初始可用内存为6000MB
#-Xmn2g :设置年轻代大小为2G
#-Xss128k :设置每个线程的堆栈大小为128k
#-XX:NewRatio=4 :设置年轻代与年老代的比值为4
#-XX:SurvivorRatio=4 :设置年轻代中Eden区与Survivor区的大小比值为4
#-XX:PermSize=512m :设置堆栈永久区起始大小为512m
#-XX:MaxPermSize=512m :设置堆栈永久区最大大小为512m
#-XX:MaxTenuringThreshold=0 :设置垃圾最大年龄为0
#-XX:+UseParallelGC :选择垃圾收集器为并行收集器
#-XX:ParallelGCThreads=8 :配置并行收集器的线程数
#-XX:+UseParallelOldGC :配置年老代垃圾收集方式为并行收集
#-XX:+UseAdaptiveSizePolicy :并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低响应时>间或者收集频率等,此值建议使用并行收集器时,一直打开。
1.2.3生产案例
根据作者本人的经验,生产环境需要确定对JVM的设置,还是需要根据java的运行状态,通过监控后,不断的调试的一个过程,没有那个配置一上来就可以适应所有的场景。以下就举列作者常用的一个JVM配置方式:
JAVA_OPTS="
-server
-Xms1024m
-Xmx1024m
-Xmn384m
-XX:PermSize=64m
-XX:MaxPermSize=128m
-XX:+UseParallelOldGC
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:/opt/tomcat/log/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/tomcat/heap.bin"
说明:
1.Xms与Xmx普遍选择配置相同的大小,实际大小根据实际情况调整,由小向大增加,没必要一开始就增加到很大的内存。
2.XX:PermSize设置堆栈永久区起始大小,XX:MaxPermSize设置堆栈永久区最大大,其实设置比默认值大写即可,或者默认也可以。作者这个这两个值,是因为出现过永久区内存溢出,才进行设定的。
3.UseParallelOldGC、PrintGCDateStamps、PrintGCDetails、Xloggc:/opt/tomcat/log/gc.log设置GClog日志,这个对分析tomcat中JVM内存使用情况非常有效。
4.XX:+HeapDumpOnOutOfMemoryError、XX:HeapDumpPath=/opt/tomcat/heap.bin"设置内存溢出时,输出HeapDump,具体如何使用分析HeapDump文件,请参考:http://vekergu.blog.51cto.com/9966832/1619640
5.作者对JVM参数设置的做法,调整合适的JVM内存大小,开启GClog和HeapDump即可。
1.3tomcat集群之session共享
1.3.1基于tomcat集群的session共享
在{TOMCST_HOME}/conf/server.xml取消下面代码注释即可:
1
1.3.2基于memcached存储session共享
具体配置方法见:http://vekergu.blog.51cto.com/9966832/1672833
1.4站点的默认网页、自定义错误页面、禁止列目录等功能
这些功能开发会在工程的WEB-INF目录下的web.xml中设置,运维了解下就好,者遇到类似问题可以找到解决思路。
1.4.1默认主页
1.4.2自定义错误页面
1.4.3定义会话超时时间
1.4.4禁止列目录
1.5管理AJP端口
AJP是为Tomcat与HTTP服务器之间通信而定制的协议,能提供较高的通信速度和效率。如果tomcat前端放的是apache的时候,会使用到AJP这个连接器。由于我们公司前端是由nginx做的反向代理,因此不使用此连接器,因此需要注销掉该连接器。在{TOMCST_HOME}/conf/server.xml中找到下列代码,注释即可
1.6取消默认gc监听
如果开启了GClog,再开启GC监听,会影响GClog输出,功能重复,可以选择取消。
1.7自定义tomcat代码路径(2015-7-21新增)
其中:
docBase这个是你代码的路径
path这个是你访问网站的URL路径,要区别path的意义,请看下面的举例
举例:
访问www.aaa.com
访问www.aaa.com/code_file
reloadable如果为true,会自动加载变化的动态文件,看起来挺智能的,但是,在tomcat加载变化代码的时候有可能会出现内存溢出,tomcat服务不正常等异常,建议还是false掉,更新完代码脚本重启tomcat才是王道。
此前看到一些文章,在讲解自定义tomcat代码路径时,reloadable全部是true,可能能多小伙伴都设置为true,建议对这个参数认真对待,否则一不小心就是一个坑。。。。
2性能优化
2.1屏蔽DNS查询
Web应用程序可以通过Web容器提供的getRemoteHost()方法获得访问Web应用客户的IP地址和名称,但是这样会消耗Web容器的资源,并且还需要通过IP地址和DNS服务器反查用户的名字。因此当系统上线时,可以将这个属性关闭,从而减少资源消耗,那么Web应用也就只能记录下IP地址。修改的属性是enableLoopups="false"。
2.2调整线程数
Tomcat通过线程池来为用户访问提供响应,对于上线的系统初步估计用户并发数量后,再调整线程池容量。例如,用户并发数量在100左右时,可以设置minProcessors="100",maxProcessors="100"。将最大和最小设置为一样后,线程池不会再释放空闲的线程,当用户访问突然增加时,不需要再消耗系统资源去创建新的线程。
2.3调整最大连接数
这个其实最复杂,即使用户并发量大,但是系统反应速度快,也没必要把这个值设置太高,高了系统需要消耗大量的资源去切换线程,但是如果设置太低也会造成应用无法满足用户并发需要。因此设置这个最好能够结合整个系统的跟踪与调优,使系统达到最好的平稳状态,一般设置为maxProcessors的1.5倍即可。
2.4调整网络超时
主要是HTTP协议也有个连接过程,客户端连接到服务器上后,如果长时间没有得到处理就会被释放。如果服务器处理速度较慢,但是希望每个用户都能得到有效处理,或者网络环境不好,需要保证用户不会因为超时中断,也可以把时间加长。但是一般设置成connectionTimeout="30000"即可。太长对系统来说价值不大,反而会浪费系统资源在无谓的长连接上。
2.5压缩管理
tomcat作为一个应用服务器,也是支持gzip压缩功能的。我们可以在server.xml配置文件中的Connector节点中配置如下参数,来实现对指定资源类型进行压缩。
compression="on"# 打开压缩功能
compressionMinSize="50"# 启用压缩的输出内容大小,默认为2KB
noCompressionUserAgents="gozilla, traviata"# 对于以下的浏览器,不启用压缩
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"# 哪些资源类型需要压缩
如果使用apache/nginx代理,所以tomcat自身不需要进行压缩,会给服务器增加压力
2.6tomcat的三种运行模式选择
2.6.1Bio
默认的模式,性能非常低下,没有经过任何优化处理和支持。
2.6.2Nio
利用java的异步io护理技术,no blocking IO技术.
想运行在该模式下,直接修改server.xml里的Connector节点,修改protocol为
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
URIEncoding="UTF-8"
useBodyEncodingForURI="true"
enableLookups="false"
redirectPort="8443"/>
启动后,就可以生效。
2.6.3Apr
安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能.。必须要安装apr和native,直接启动就支持apr。
安装APR
sudoyum -yinstallapr apr-devel
tarzxvf tomcat-native.tar.gz//该文件在tomcat的bin目录下面
cdtomcat-native-1.1.24-src/jni/native
./configure--with-apr=/usr/bin/apr-1-config
make
makeinstall
安装完成之后会出现如下提示信息
Libraries have been installed in:
/usr/local/apr/lib
安装成功后还需要对tomcat设置环境变量,方法是在catalina.sh文件中增加一行:
CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib"
修改8080端对应的
protocol="org.apache.coyote.http11.Http11AprProtocol"
2.7Tomcat连接相关参数总结
在Tomcat配置文件server.xml中的配置中
maxThreads 客户请求最大线程数
minSpareThreads Tomcat初始化时创建的 socket 线程数
maxSpareThreads Tomcat连接器的最大空闲 socket 线程数
enableLookups 若设为true, 则支持域名解析,可把 ip 地址解析为主机名
redirectPort 在需要基于安全通道的场合,把客户请求转发到基于SSL 的 redirectPort端口
acceptAccount 监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads )
connectionTimeout 连接超时
minProcessors 服务器创建时的最小处理线程数
maxProcessors 服务器同时最大处理线程数
URIEncoding URL统一编码
compression 打开压缩功能
compressionMinSize 启用压缩的输出内容大小,这里面默认为2KB
compressableMimeType 压缩类型
connectionTimeout 定义建立客户连接超时的时间. 如果为 -1, 表示不限制建立客户连接的时间
2.8生产配置实例
URIEncoding="UTF-8"#设置编码
minSpareThreads="25"#Tomcat初始化时创建的 socket线程数
maxSpareThreads="75"#Tomcat连接器的最大空闲socket 线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。默认值50
enableLookups="false"#屏蔽DNS查询
disableUploadTimeout="true"#该标志位表明当执行servlet时,是否允许servlet容器使用一个不同的、更长的连接超时。启用该标志位将导致在上传数据时,要么使用更长的时间完成上传,要么出现更长的超时。如果不指定,该属性为“false”。
connectionTimeout="20000"#网络超时时间
acceptCount="300"#容许的最大连接数,一般设置为maxProcessors的1.5倍即可,满了之后客户请求会被拒绝(不能小于maxSpareThreads )
maxThreads="300"#客户请求最大线程数,默认值为“200”
maxProcessors="1000"#最大连接线程数,即:并发处理的最大请求数,默认值为75 ,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程
minProcessors="5"#最小空闲连接线程数,用于提高系统处理性能,默认值为10
useURIValidationHack="false"
compression="on"#打开压缩功能
compressionMinSize="2048"#启用压缩的输出内容大小,这里面默认为2KB
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"#压缩类型
-->
redirectPort="8443"/>
3安全优化
3.1tomcat影藏版本信息
Tomcat安装目录下的lib目录下,名称为catalina.jar,直接修改catalina.jar中的文件,org/apache/catalina/util/ServerInfo.properties
server.info=Apache Tomcat/7.0.53
3.2禁用Tomcat管理页面
我们线上是不使用Tomcat默认提供的管理页面的,因此都会在初始化的时候就把这些页面删掉。这些页面是存放在Tomcat安装目录下的webapps目录下的。我们只需要删除该目录下的所有文件即可。当然,还有涉及管理页面的2个配置文件host-manager.xml和manager.xml也需要一并删掉。这两个文件存放在Tomcat安装目录下的conf/Catalina/localhost目录下。
3.3用普通用户启动Tomcat
为了进一步安全,我们不建议使用root来启动Tomcat。这边建议使用专用用户tomcat或者nobody用户来启动Tomcat。在启动之前,需要对我们的tomcat安装目录下所有文件的属主和属组都设置为指定用户。
3.4分离Tomcat和项目的用户
为了防止Tomcat被植入web shell程序后,可以修改项目文件。因此我们要将Tomcat和项目的属主做分离,这样子,即便被搞,他也无法创建和编辑项目文件。
3.5关闭war自动部署
默认Tomcat是开启了对war包的热部署的。为了防止被植入木马等恶意程序,因此我们要关闭自动部署。
修改实例:
1
2
3
unpackWARs="false"autoDeploy="false">
3.6更改关闭Tomcat实例的指令
server.xml中定义了可以直接关闭Tomcat实例的管理端口。我们通过telnet连接上该端口之后,输入SHUTDOWN(此为默认关闭指令)即可关闭Tomcat实例(注意,此时虽然实例关闭了,但是进程还是存在的)。由于默认关闭Tomcat的端口和指令都很简单。默认端口为8005,指令为SHUTDOWN。因此我们需要将关闭指令修改复杂一点。
当然,在新版的Tomcat中该端口仅监听在127.0.0.1上,因此大家也不必担心。除非黑客登陆到tomcat本机去执行关闭操作。
修改实例:
1
4内核优化
在修改内核参数的时候,建议大家逐个设置,然后反复试验,切勿图方便直接拿上就用,一次全部替换。
优化网络参数
修改/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 915000000927000000
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 65536
保存退出,执行sysctl-p生效
内核参数详细作用,可以参考:http://blog.chinaunix.net/uid-21505614-id-2181210.html