Tomcat 功能说明与配置说明.
理论基础
Tomcat服务安装启动
- 1.官网下载JDK与Tomcat直接解压,JDK7对应Tomcat7,JDK8对应Tomcat8
配置
JAVA_HOME配置
windows setclasspath.bat文件最前面加上:
1 | set JAVA_HOME=D:\java\jdk1.8.0_171 |
linux setclasspath.sh文件最前面加上:
1 | JAVA_HOME="/usr/local/java/jdk1.8.0_171" |
Tomcat 7.0.100.0 Log4j配置,对tomcat大日志进行切割
$CATALINA_BASE/lib
目录创建log4j.properties
文件注意里面语法与包路径不同版本会有所区别具体参考官方文档,添加log4j.jar必须v1.2.x版本- 去官网下载扩展组件
Extras
:tomcat-juli.jar和tomcat-juli-adapters.jar到lib
目录,复制tomcat-juli.jar到bin
目录 - 删除
logging.properties
- 启动tomcat
tomcat7 log4j.properties
配置例子:
1 | log4j.rootLogger=INFO, CATALINA |
还有其他分隔方案比如:
- 创建shell脚本进行catalina.out日志文件切割,使用linux自带定时器。(执行脚本的定时任务的频率以及时间都要控制好,不然可能会有部分日志内容保存不下来的情况)
- 用cronolog软件来分割Tomcat的catalina.out文件
- 使用logrotate软件来切割日志文件
cat /var/lib/logrotate/logrotate.status
查看切割状态,logrotate有两个条件,一个是保存多少天日志,还有一个是size超过多大才进行分割
配置资源gzip压缩
1 | <Connector port="8090" protocol="HTTP/1.1" |
compression=”on” 开启压缩。可选值:”on”开启,”off”关闭,”force”任何情况都开启
compressionMinSize=”2048”大于2KB的文件才进行压缩,默认2048B。如果配置不合理,产生的后果是小文件压缩后反而变大了,达不到预想的效果
noCompressionUserAgents=”gozilla, traviata”,对于这两种浏览器,不进行压缩
compressableMimeType=”text/html,text/xml,application/javascript,text/css,text/plain,text/json”会被压缩的MIME类型列表,多个逗号隔,表明支持html、xml、js、css、json等文件格式的压缩
Connector 参数说明
- port 指定端口accept客户端的链接
- protocol “HTTP/1.1”是默认值,等效于”org.apache.coyote.http11.Http11Protocol”,在Tomcat 6.0之后,还提供了NIO的方式,可以有效的提升性能,特别是在大量长连接/数据上传+下载等web应用中.此时portocal=”org.apache.coyote.http11.Http11NioProtocol”
BIO:JDK 1.5+,tomcat 5.x+
NIO:JDK 1.6+,tomcat 6.x+
NIO2:JDK 1.7+,tomcat 7.x+ - maxParameterCount http-get请求中允许传递的查询字符串的最大个数,”-1”表示无限制,为了安全和规范,maxHeaderCount和maxParamterCount通常应该合理,建议设置为100等;如果请求参数再多,那么就建议使用post body发送或者拆分请求
- maxPostSize http-post请求中数据(body)的最大尺寸,单位:byte,默认值为2M
- URIEncoding http-get请求中,使用何种字符集对查询字符串进行编码,默认为”iso-8859-1”
- useBodyEncodingForURI 是否使用”Content-type”中指定的编码方式对http-get请求中查询字符串进行编码.如果为”true”,将会忽略”URIEncoding”配置项,转而使用header中”content-Type”指定的编码方式
- maxThreads 用于接收和处理client端请求的最大线程数,默认200,太大的值,并不能提升NIO性能,反而会使性能下降,因为线程切换(CS)将会占据CPU的大量时间
- compression 是否对http相应数据启用Gzip压缩
- acceptCount 当tomcat请求处理线程池中的所有线程都处于忙碌状态时,此时新建的链接将会被放入到pending队列,acceptCount即是此队列的容量,如果队列已满,此后所有的建立链接的请求(accept),都将被拒绝。默认为100。在高并发/短链接较多的环境中,可以适当增大此值;当长链接较多的场景中,可以将此值设置为0.
- address 当物理server上绑定了多个IP地址时,可以通过“address”来指定tomcat-server需要bind的地址.默认将port关联到所有的ip上
- bufferSize 链接在读取stream时,buffer数据的尺寸
- connectionLinger socket linger参数值。当socket即将关闭时(前)阻塞的时间,单位:秒。如果设置为-1,表示关闭linger。在BIO(Blocking IO)和AJP链接中默认为100,NIO中默认为25
- keepAliveTimeout 当无实际数据交互时,链接被保持的时间,单位:毫秒。在未指定此属性时,将使用connectionTimeout作为keepAliveTimeout。对于HTTP请求,server端为了支撑较高的吞吐量,不可能无限制的keepAlive一个链接(在设计要求上,这个和TCP通讯有本质的区别),keepAliveTimeout超时后,将会导致链接关闭。如果此tomcat设计为“长链接”服务,可以适当增加keepAliveTimeout值,否则无需设置此值。不过我们通常在tomcat上层还有nginx等代理服务器,我们通常希望链接keepAlive的机制由代理服务器控制,比如nginx来决定链接是否需要“保持活性”(注意,与keep_alive不同),当然nginx服务器只会保留极少的长连接,几乎所有的链接都会在使用结束后主动close;因为链接复用层,将有nginx与client保持,而不再是tomcat与client保持。太多的keepAlive链接,尽管提高了链接使用效率,但是对负载均衡不利。
- maxKeepAliveRequests tomcat需要保持的最大请求数,即处于keepAlive状态的请求的个数,建议此值为maxThreads * 0.5,不得大于maxThreads,否则将得不到预期的效果。-1表示不限制,1表示关闭keepAlive机制。
- maxConnections tomcat允许接收和处理的最大链接数,对于BIO而言此值默认与maxThreads参数一样,对于NIO而言此值默认为10000。
- acceptorThreadCount 默认为1,表示用于accept新链接的线程个数,如果在多核CPU架构下,此值可以设置为2,官方不建议设定超过2个的值。
- maxHttpHeaderSize http头的最大尺寸,默认为8192,单位为“字节”。
- minSpareThreads 线程池中,保持活跃的线程的最小数量,默认为10
- SSLEnabled 是否开启ssl支持,默认为false;通常SSL应该在nginx等代理层,我们不应该让tomcat直接接入
- pollerThreadCount 表示用于polling IO事件的线程个数,默认为1。NIO
- useSendfile 是否开启sendfile特性,默认为true。对于web应用而言,通常project中还会包含一定数量的静态资源,比如图片、CSS、js、html等,sendfile在一定程度上可以提高性能。NIO
- selectorTimeout 选择器阻塞的时间,如果你进行过NIO开发,应该知道此参数的含义,默认值为1000毫秒。此值不要太大,因为selector线程本身还需要用来清理已关闭的链接等。NIO
- selectorPool.maxSelectors:NIO中选择的个数,默认值为200。NIO
内存大小配置
整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小
修改tomcat下catalina.sh
里,位置cygwin=false
前
1 | OS specific support. $var _must_ be set to either true or false. |
-Xms
初始堆内存大小,一般设置为和Xmx一致,避免每次垃圾回收后重新分配内存-Xmx
堆最大可用内存-XX:NewSize
初始新生代大小-XX:MaxNewSize
最大新生代大小-Xss
设置每个线程栈的大小-XX:PermSize
JVM初始非堆内存、持久代、物理内存的1/64-XX:MaxPermSize
JVM最大非堆内存、持久代、物理内存的1/4-XX:NewRatio
新生代与老年代比例,默认1:2也就是1/3新生代,-XX:SurvivorRatio=8
默认的,Eden : from : to = 8 : 1 : 1, Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小,JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的-XX:MaxTenuringThreshold=15
一个对象每次Minor Gc时,活着的对象都会在s0和s1区域转移,经过经过Minor GC 15次后会进入Old区域-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M
JAVA8 替代永久代的元空间-XX:+UseSerialGC
设置串行收集器-XX:+UseParallelGC
设置并行收集器-XX:+UseParalledlOldGC
设置并行年老代收集器-XX:+UseConcMarkSweepGC
设置并发收集器-XX:ParallelGCThreads=n
设置并行收集器收集时使用的CPU数。并行收集线程数。-XX:MaxGCPauseMillis=n
设置并行收集最大暂停时间-XX:GCTimeRatio=n
设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)-XX:+CMSIncrementalMode
设置为增量模式。适用于单CPU情况。-XX:ParallelGCThreads=n
设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。-XX:+PrintGC
统计信息
在发生FULL GC的时候,意味着JVM会安全的暂停所有正在执行的线程(Stop The World),来回收内存空间,在这个时间段内,所有除了回收垃圾的线程外,其他有关JAVA的程序,代码都会静止,反映到系统上,就会出现系统响应大幅度变慢,卡机等状态。
Java8永久代被移除,增加元空间。
垃圾收集:引用计数、可达性分析、标记清除法、标记整理法、复制算法。串行收集器、并行收集器、并发收集器
查看JVM内存使用情况:
1 | ps -ef | grep tomcat # 查看进程号 |
清除缓存
删除tomcat/work
目录下面的文件与文件夹
redhat6开机自启动
cd /etc/init.d
vi tomcat8-xxx-spi
拿catalina.sh改也行,加上前面9行。不想显示tomcat8还可以根据自己需求修改成其他名字1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23!/bin/bash
description: Tomcat Start Stop Restart
processname: tomcat
chkconfig: 234 20 80
JAVA_HOME=/usr/java/jdk1.8.0_131
export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH
export PATH
CATALINA_HOME=/home/infotech/project/xxx-spi-xxx-8888
case $1 in
start)
sh $CATALINA_HOME/bin/startup.sh
;;
stop)
sh $CATALINA_HOME/bin/shutdown.sh
;;
restart)
sh $CATALINA_HOME/bin/shutdown.sh
sh $CATALINA_HOME/bin/startup.sh
;;
esac
exit 0chmod 755 tomcat8-xxx-spi
chkconfig --add tomcat8-xxx-spi
chkconfig --level 234 tomcat8-xxx-spi on
chkconfig --list tomcat8-xxx-spi
service tomcat8-xxx-spi start
通过命令启动服务service tomcat8-xxx-spi stop
通过命令关闭服务
centos7开机自启动
- 系统(/user/lib/systemd/system/)、用户(/etc/lib/systemd/user/)
vi /usr/lib/systemd/system/tomcat-test.service
新建一个tomcat-test服务1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19[Unit]
Description=tomcat
After=syslog.target network.target # 在指定服务后运行
[Service]
User=infotech # 运行用户 一般都需要指定用户,可以不配置Type使用默认
Type=forking # 后台运行,simple(默认值)
PIDFile=/home/infotech/project/tomcat-test-8888/tomcat-test.pid # 开启后必须在catalina.sh加入CATALINA_PID,这个非常有必要
Environment="JAVA_HOME=/usr/java/jdk1.8.0_131" # 设置环境变量
WorkingDirectory=/home/infotech/project/tomcat-test-8888/
ExecStart=/home/infotech/project/tomcat-test-8888/bin/startup.sh # 脚本中的命令都需要使用全路径
ExecStop=/home/infotech/project/tomcat-test-8888/bin/shutdown.sh
ExecReload=/bin/kill -s HUP $MAINPID
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target # 多用户模式启动- 如果设置了PIDFile需要在tomcat
bin/catalina.sh
中加入CATALINA_PID参数1
2
3
4
5
6CATALINA_PID=/home/infotech/project/tomcat-test-8888/tomcat-test.pid
OS specific support. $var _must_ be set to either true or false.
cygwin=false
... systemctl daemon-reload
使服务生效systemctl enable tomcat-test.service
设置为开机启动systemctl start tomcat-test.service
启动服务systemctl status tomcat-test.service
监测服务状态systemctl list-units --type=service
显示已启动服务
虽然可以自启而且可以保障通过systemctl命令只启动一个tomcat,但是如果使用tomcat/bin/startup.sh来启动tomcat还是会导致启动多个程序,所以得设置pid来避免重复启动,或者关闭脚本改用kill -9 xxx
命令实现或者killall java
来实现会关闭所有tomcat程序。systemctl与直接用脚本启动的程序是独立的,需要用pid来约束。配置参数等等都得正确,否则直接调用脚本启动呢的tomcat,调用tomcat自带的关闭脚本无法关闭新启动的进程,导致出现两个进程。某些情况出现tomcat无法通过shutdown.sh正常关闭需要用kill实现,之前出现过netty程序启动着无法关闭的情况,当然应该还是有办法通过优化程序避免这种问题的,最直接的还是用kill -9实现。简单点就算统一使用systemctl启动关闭tomcat程序这样,也是不会出现多个程序的情况的,直接调用startup脚本会不受控制。
tomcat-test.service增加PIDFile=/home/infotech/project/tomcat-test-8888/bin/tomcat-test.pid
,增加PID还是非常有必要的。
安全加固
禁用TRACE
修改tomcat/server.conf文件,增加allowTrace="true"
。加完使用postman测试下
1 | <Connector port="8080" protocol="HTTP/1.1" |
如下方法在tomcat/conf/web.xml最后加上一个节点,除了TRACE方法不生效,其他方法可以生效。测试发现在linux下还是不生效
1 | <security-constraint> |
在代码中过滤TRACE请求
1 | // 比如在请求过滤器RequestFilter中增加,只允许让POST、GET,或者针对性过滤 |
CSRF
CSRF Prevention Filter
安全漏洞
禁用RC4、DES,CVE-2015-2808,CVE-2016-2183
修改tomcat/conf/server.xml
配置文件,找到https端口配置
1 | <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" |
RC4与DES/AES一样是一种对称加密算法。TLS_RSA_WITH_AES_128_CBC_SHA256:TLS–SSL还是TSL,RSA–所用非对称加密算法,AES–所用对称加密算法,128–对称加密分组长度,CBC–分组加密模式,SHA256–所用完整性验证算法
检测到目标主机可能存在缓慢的HTTP拒绝服务攻击
修改超时时间,通过SlowHTTPTest工具测试
1 | 测试命令 |
1 | tomcat 相关配置项目 |
其他
强制关闭
1 通过命令
通过ps -ef|grep tomcat
查看进程号 通过kill -9 pid
关闭
2 通过配置
- 在
catalina.sh
开头第二行加入CATALINA_PID="tomcat.pid"
或者CATALINA_PID="/var/run/tomcat.pid"
pid文件存放目录,不推荐用该方法 ./catalina.sh -help
查看具体参数- 修改
catalina.sh
,推荐使用,重复启动会提示Existing PID file found during start
。启动关闭的时候会创建pid与删除pid文件1
2
3
4
5PRGDIR=`dirname "$PRG"` # 后面加入下面语句
if [ -z "$CATALINA_PID" ]; then
CATALINA_PID=$PRGDIR/CATALINA_PID
cat $CATALINA_PID
fi shutdown.sh 3 -force
关闭,或者./catalina.sh stop -force
一条命令或写成脚本
ps -elf | grep tomcat | grep -v grep | awk '{print $4}' | xargs kill -9
awk '{print $4}'
每行按空格或TAB分割,输出文本中的第4项xargs
给命令传递参数
源码
1 | /** |
部署
多个应用部署在同一个tomcat有好有坏吧,好处维护少一点,得一起开一起关闭。
问题排查
出问题最先该做的就是打开日志,查看日志。
如何修改上传文件的默认权限
Tomcat Linux修改上传文件默认权限
编辑tomcat根目录/bin/catalina.sh
文件,找到
1 | # Set UMASK unless it has been overridden |
将0027根据需要改成0022或者其他,重启
修改https配置
如果把https修改成http,浏览器需要关闭重新开,不然无法登录,可能浏览器会认为服务器支持https,走到https流程。
支持IPv6
tomcat8支持ipv6与ipv4。虽然netstat -tnl
只显示ipv6,其实是都支持的,可以到本机使用telnet ipv6与端口进行尝试。如果其他服务器无法通过ipV6连接到对方服务大概率就算使用的交换机或者路由器不支持IPv6了。
可以到server.xml中添加address参数详细配置监听地址。
提供文件服务
增加一个配置项映射,就可以跟Nginx一样对外提供文件访问服务。
1 | <Context path="/abc-data" docBase="/data/ftp/images"/> |
升级包可能出现问题
升级包tar.gz不要把原先目录改成文件,这样同名文件无法覆盖成功会出问题。
版本运维
通过jenkins自动从svn拉取项目自动部署还是挺好用的。
问题
webapps里面相同项目拷贝了两个,一个叫做xxx_bak结果代码功能都是一样的导致冲突问题。看日志可以看出来,程序重复初始化2次等等。
基于Tomcat的WEB应用使用到了Kafka服务
有遇到过tomcat内部文件权限被改错,导致整个程序起来的时候IO吃到满的情况,用root用户启动就正常,把tomcat内部文件权限都改对了就可以正常启动了。
进行了如下尝试最后正常了:
可能不完全是权限问题,有把kafka注释就能启动
也可能groupid冲突了,修改groupid,两个用到的程序都得重启
尝试使用root权限启动tomcat
普通用户情况可能war包也不能是root权限,修改tomcat下所有文件权限为普通用用户,普通用户重启,正常启动
最可能的是:tomcat下已有且只有非root用户解压出来的文件夹,此时上传root权限的war包会导致大量IOwait
JDK TOMCAT版本对应关系 Servlet
项目启动的时候会有提示信息,可以根据提升选择版本。
Maven Springboot项目可以搜索spring-boot-starter-tomcat
2.7.x默认集成的是tomcat9,使用servlet4.0。
启动慢问题
openjdk环境中java项目启动慢的问题
可能是openjdk在启动时会去获取hostname,如果未设置就会卡很久。
在服务器上/etc/hosts中加入ip与hostname即可解决,hostname命令查看主机名
echo "21.22.22.xx localhost localhost.localdomain" >> /etc/hosts
现网成功解决启动慢问题
参考
- Logging in Tomcat
- Tomcat中Connector常用配置及问题解决
- servlet3与servlet4区别和实现
- tomcat如何配置https
- Tomcat笔记:Tomcat的执行流程解析
- SlowHTTPTest Package Description
- Identifying Slow HTTP Attack Vulnerabilities on Web Applications
- slowhttptest (1) - Linux Man Pages
- tomcat配置说明
- 谈谈 TCP 的 TIME_WAIT
- logrotate tomcat 日志切割
- 日志切割工具logrotate解决Tomcat catalina.out日志过大的问题
- linux下文件权限更改
- linux tomcat 创建文件没有权限,tomcat创建的文件权限和linux umask、acl
- 【systemd】关于 Active: active (exited)
- 分割tomcat的catalina.out日志
- logrotate 的使用简介