tomcat 相关(性能调优 安全 目录列表 IP控制 端口 https ) JVM参数
tomcat8 的优化与安全配置
2012/06/01 Chenxin
2019/06/23 Chenxin update
参考:
https://blog.csdn.net/qq_29663071/article/details/79789615
粗体字部分为实际配置到环境中的参数
涉及到的文件
/home/coinw/tomcat_web/conf/server.xml # xml配置
/home/coinw/tomcat_web/bin/setenv.sh # jvm配置
/home/coinw/tomcat_web/webapps/ # 清空
JSP解析说明
只有当客户端第一次请求JSP时,才需要将其转换、编译
优点: 优良的性能(优于CGI,PHP,ASP);平台无关性(操作系统无关,Web服务器无关);可扩展性(tag的扩展机制,简化页面开发).
JSP解析过程:
1JSP先把文件解析成java文件
2然后再通过javac把java文件编译成类文件
3再通过JVM虚拟机把类文件转换成html
4把html给客户端
安全性-隐藏版本(优化server.xml)
确认版本号
./catalina.sh version
Using CATALINA_BASE: /home/coinw/tomcat_web
...
Server version: Apache Tomcat/8.0.47
...
OS Name: Linux
OS Version: 3.10.0-957.el7.x86_64
Architecture: amd64
JVM Version: 1.8.0_221-b11
隐藏版本信息
隐藏HTTP 头部的版本信息
客户端访问资源的时候(F12)看到版本 Server:Apache-Coyote/1.1
编辑server.xml: vi /usr/local/tomcat8/conf/server.xml 为Connector 添加 server 属性
隐藏方法
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
...
server="nginx 1.17.2"/>
隐藏404页面出现的版本号 (当前打开的404已由程序自动处理,显示404)
第一种方法
针对该信息的显示是由一个jar包控制的,该jar包存放在 Tomcat 安装目录下的lib目录下,名称为 catalina.jar。
我们可以通过 jar xf 命令解压这个 jar 包会得到两个目录 META-INF 和 org ,通过修改 org/apache/catalina/util/ServerInfo.properties 文件中的 serverinfo 字段来实现来更改我们tomcat的版本信息。
文件信息如下:
[root@localhost ~]# cat /usr/local/tomcat8/lib/org/apache/catalina/util/ServerInfo.properties |grep -v '^$|#'
server.info=Apache Tomcat/8.0.23
server.number=8.0.23.0
server.built=Mar 18 2016 20:31:49 UTC
第二种方法
实现隐藏或伪装Tomcat的版本信息,其本质和上面一样,操作如下:
[root@localhost ~]# cd /usr/local/tomcat8/lib
[root@localhost lib]# mkdir -p org/apache/catalina/util
[root@localhost lib]# cd org/apache/catalina/util
[root@localhost util]# vim ServerInfo.properties
server.info=nolinux # 如果想修改成其它版本号,把这个地方的值改成其它值就行了
修改效果如下:...nolinux
禁用Tomcat管理界面
1.生产环境一般不适用Tomcat默认的管理界面,这些页面存放在Tomcat 的webapps安装目录下,把该目录下的所有文件删除即可:rm -rf /usr/local/tomcat8/webapps/*
2.另外删除相关的配置文件 host-manager.xml 和 manager.xml,在Tomcat 安装目录 conf/Catalina/localhost目录下。注释或删除tomcat_user.xml 中的所有用户权限。
目前8.0版本只需要"1".其他配置文件里,默认也是注释的.
应用程序安全(自动部署)
tomcat默认开启了对war热部署。为了防止被植入木马恶意攻击,我们要关闭war包自动部署。
关闭自动加载最新代码(设置reloadable)
修改实例:
coinw项目如下(unpackWARs为false则启动异常):
更改关闭Tomcat的默认指令
server.xml中定义了可以直接关闭 Tomcat 实例的管理端口。我们通过 telnet 连接上该端口之后,输入 SHUTDOWN (此为默认关闭指令)即可关闭 Tomcat 实例(注意,此时虽然实例关闭了,但是进程还是存在的)。由于默认关闭 Tomcat 的端口和指令都很简单。默认端口为 8005,指令为SHUTDOWN 。因此我们需要将关闭指令修改复杂一点。
当然,在新版的 Tomcat 中该端口仅监听在127.0.0.1上,因此大家也不必担心。除非黑客登陆到tomcat本机去执行关闭操作。
修改实例:
或者禁用8005端口 (会导致无法正常关闭tomcat)
执行tomcat进程用户权限(防止该用户获取到bash权限) 暂未做,稍显复杂,不易管理
不要默认使用root用户启动tomcat。
Java程序与C程序不同。nginx,httpd 使用root用户启动守护80端口,子进程/线程会通过setuid(),setgid()两个函数切换到普通用户。即父进程所有者是root用户,子进程与多线程所有者是一个非root用户,这个用户没有shell,无法通过ssh与控制台登陆系统.
Java 的JVM 是与系统无关的,是建立在OS之上的,你使用什么用户启动Tomcat,那麽Tomcat 就会继承该所有者的权限。为了防止 Tomcat 被植入 web shell 程序后,通过shell修改项目文件。
以下新建一个tomcat用户,并以tomcat用户权限启动tomcat进程,之后取消bash环境(无bash权限.因coinw还需要经常bash,所以不用coinw账号)
useradd tomcat -s '/sbin/nologin'
usermod -a -G coinw tomcat
然后在tomcat的家目录下,把coinw用户对应tomcat/webapps/的目录实时同步至此(可以采用rsync+inotify方案).将文件属组改为tomcat.tomcat.
以tomcat用户权限执行start.sh脚本.在root账号下执行以下:
!/bin/bash
set user tomcat to /bin/bash to start server
usermod -s /bin/bash tomcat
use tomcat user to start server
su - tomcat -c /usr/local/tomcat_web/bin/startup.sh # 或者 sudo -u tomcat ./startup.sh
set user tomcat to /sbin/nologin
usermod -s /sbin/nologin tomcat
说明
usermod -G groupname username (把用户从其他组中去掉,只属于该组).
usermod -a -G groupname username (把用户添加到这个组,之前所属组不影响)
完整删除用户: serdel -r username
这个方法只是防止执行tomcat进程的用户获取系统shell权限.
性能优化-连接池配置
使用线程池,用较少的线程处理较多的访问,可以提高tomcat处理请求的能力。
编辑配置文件 /usr/local/tomcat8/conf/server.xml
1.打开被注释的连接池配置
默认配置:
修改为:
参数讲解:
name: 线程名称
namePrefix: 线程前缀
maxThreads : 最大并发连接数,不配置则默认200,建议500~ 800.
minSpareThreads:Tomcat启动初始化的线程数,默认25
prestartminSpareThreads:在tomcat初始化的时候就初始化minSpareThreads的值, 不设置true时minSpareThreads
maxQueueSize: 最大的等待队列数,超过则拒绝请求
2.修改链接配置
默认配置:
修改配置:
推荐配置: 取消压缩(tomcat压缩不如nginx效率高)
参数讲解:
port:连接端口。
protocol:连接器使用的传输方式。 Tomcat 8 设置 nio2 更好:org.apache.coyote.http11.Http11Nio2Protocol protocol, Tomcat 6、7 设置 nio 更好:org.apache.coyote.http11.Http11NioProtocol 注:每个web客户端请求对于服务器端来说就一个单独的线程,客户端的请求数量增多将会导致线程数就上去了,CPU就忙着跟线程切换。而NIO则是使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由线程池来处理堵塞在pipe 或者队列里的请求.这样的话,只要OS可以接受TCP的连接,web服务器就可以处理该请求。大大提高了web服务器的可伸缩性。
executor: 连接器使用的线程池名称.跟Executor同名.
enableLookups:禁用DNS 查询.enableLookups 若设为true, 则支持域名解析,可把 ip 地址解析为主机名.
acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认设置 100 。
maxPostSize:限制 以FORM URL 参数方式的POST请求的内容大小,单位字节,默认是 2097152(2兆),10485760 为 10M。如果要禁用限制,则可以设置为 -1。
acceptorThreadCount: 用于接收连接的线程的数量,默认值是1。一般这个指需要改动的时候是因为该服务器是一个多核CPU,如果是多核 CPU 一般配置为 2。
compression:传输时压缩。
compressionMinSize:压缩的大小
noCompressionUserAgents:不启用压缩的浏览器.
提示:压缩会增加Tomcat负担,最好采用Nginx + Tomcat 方式,压缩交由Nginx/Apache 去做.
性能优化-管理AJP端口(无需设置)
AJP是为 Tomcat 与 HTTP 服务器之间通信而定制的协议,能提供较高的通信速度和效率。如果tomcat前端放的是apache的时候,会使用到AJP这个连接器。 默认是开启的。如果不使用apache,注释该连接器。
tomcat8.0 默认:
性能优化 - tomcat catalina.sh JAVA_OPTS 优化(JVM)
20130502 Chenxin整理
20190806 Chenxin update
一.优化步骤
1.增加CPU个数;
2.增加内存;
3.调整JVM参数;
4.调整tomcat配置文件参数
5.修改软件架构,调整逻辑结构
6.机器累加,做集群
二.JVM优化
Tomcat容器是运行在JVM上的, 其默认内存一般都很小(物理内存的1/64). 对于JVM的优化主要有两个方面: 内存调优 和 垃圾收集策略调优.
用户自定义参数的放置路径
catalina.sh 文件里的注释,要求放到对应目录.CATALINA_BASE/bin 也就是 /home/coinw/tomcat_web/bin/
Do not set the variables in this script. Instead put them into a script
setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
创建 setenv.sh
cat /home/coinw/tomcat_web/bin/setenv.sh
export CATALINA_OPTS="$CATALINA_OPTS -Xms10240m -Xmx10240m -Xmn2048m -Xss256K -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC"
知识
1.内存占用说明
Tomcat 的运行内存 = Xmx(初始内存大小) + Perm Generation(JDK 7中的永久代大小) + Java应用创建的线程数 * 1MB.
Java 应用每创建一个线程, JVM 进程的内存中就会创建一个 Thread 对象, 同时也会在操作系统中创建一个真正的物理线程.操作系统会在 Tomcat 的空闲内存中创建这个物理线程, 而不是在 JVM 的 Xmx 堆内存中创建.
在 JDK 1.4中, 默认的栈大小是256KB/线程, 自 JDK 5开始, 默认的栈大小变为1M/线程. 如果系统剩余内存为400M, 则应用最多能创建400个可用线程.那么,要想创建更多的线程, 必须减少分配给JVM的最大内存.
2.内存配置相关参数
cat setenv.sh
export CATALINA_OPTS="$CATALINA_OPTS -server -Xms10240m -Xmx10240m -Xmn2048m -Xss256K -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC"
-server # JVM的server模式, 多CPU中性能更好地发挥. 默认client(弱). 配置server模式时要将其作为第一个参数.
-Xmx4g # Java Heap的最大可用内存, 默认为物理内存的1/4. 只运行Tomcat, 建议为内存的50%~80%.
-Xms4g # Java Heap的初始大小, 默认为物理内存的1/64.建议跟Xmx相同.
-Xss128k # 每个线程的Stack大小. 在相同物理内存下, 减小这个值能生成更多的线程,但是操作系统对一个进程内的线程数是有限制的, 经验范围是3000~5000.
-XX:NewRatio=4 # 设置新生代(包括Eden和两个Survivor区)与老年代的比值(除去持久代), 默认为2, 即新生代与老年代所占比值为1:2, 新生代占整个堆栈的1/3.
-XX:SurvivorRatio=4 # 设置新生代中Eden区与1个Survivor区的大小比值. 默认8, 即Eden区占新生代80%, 2个Survivor分别占新生代的10%.设置为4, 则两个Survivor区与一个Eden区的比值为2:4, 一个Survivor区占整个新生代的1/6.
-Xmn1024m # 设置Young Generation所占用的Java Heap大小为1g. 此值对系统性能影响较大, Sun官方推荐配置为整个堆的3/8(或Xmx的1/4~1/3左右).也可使用-XX:NewSize和-XX:MaxNewsize设置新生代的初始值和最大值.注意: -Xmn 与 -XX:NewSize、-XX:MaxNewSize 的优先级: -XX:NewRatio的值会被忽略.1. 高优先级: -XX:NewSize/-XX:MaxNewSize. 2. 中优先级: -Xmn, 等效于同时设置 -Xmn = -XX:NewSize = -XX:MaxNewSize 三者的值. 3. 低优先级: -XX:NewRatio. -Xmn参数是在JDK 1.4 开始支持, 推荐使用之.
-XX:NewSize=1g # 设置新生代的大小, 默认为1.25MB. 若显示设置此值, 将使得NewRatio选项失效.
-XX:OldSize=2g # 设置老年代的大小, 默认为5.1875MB.
-XX:PermSize=128m # JDK 7及以下版本适用: 设置Java Heap中永久代的初始大小, 默认为20.75MB
-XX:MaxPermSize=256m # JDK 7及以下版本适用: 设置Java Heap中永久代的最大值. 默认为82.0MB
-XX:MetaspaceSize=128m # JDK 8及以上版本适用: 初始元空间的大小, 默认为21MB
-XX:MaxMetaspaceSize=256m # JDK 8及以上版本适用: 最大元空间的大小. 默认无上限
总结:
- 情形一: 如果不指定Xmx、Xms和NewSize、OldSize, 则系统将基于Xms=1/64总内存大小, 对各个Space按照NewRatio=2进行空间的分配, 此时NewSize与OldSize的默认大小将失效.
- 情形二: 如果指定了Xmx、Xms, 未指定NewSize、OldSize, 则系统将优先满足 NewRatio=2, 且OldSize+NewSize=Xms, 此时NewSize与OldSize的默认大小将失效.
- 结论: 除非显式指定NewSize与OldSize的值, 否则它们的默认配置一般都不会得到满足. 显式指定其中任一个, 另一个就会基于默认值, 并根据应用程序的消耗动态分配空间大小.
GC策略调优实践
Tomcat的GC策略一般都是与其内存参数一起配置的, 与应用复杂度相匹配的GC策略、与服务器性能相适应的内存比例, 都将使得系统性能得到大幅提升.
以JDK 8、Tomcat 8为例, 服务器内存为126GB, 作出如下配置:
以下放到此文件里:/home/coinw/tomcat_web/bin/setenv.sh
配置内存
JAVA_OPTS="-server -Xmx96g -Xms96g -Xmn35g -XX:OldSize=55g -Xss128k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m"
配置GC策略
JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15 -XX:CMSInitiatingOccupancyFraction=40 -XX:CMSFullGCsBeforeCompaction=0 -XX:+ExplicitGCInvokesConcurrent -XX:SoftRefLRUPolicyMSPerMB=0 -XX:MaxGCPauseMillis=100 -Xnoclassgc "
tomcat https 配置 (等待测试)
参考:
https://blog.csdn.net/yiyihuazi/article/details/82935380
https://www.cnblogs.com/franson-2016/p/8269608.html
https://www.cnblogs.com/longLifeFrog/p/9067147.html
JDK8+Tomcat8配置https
生成密钥对
生成密钥对的命令是keytool -genkeypair,在原先的有的jdk所提供的命令是keytool -genkey,但我感觉jdk8的这种表达更为明确一些。
keytool -genkeypair -alias tomcat -keyalg RSA -keypass password -storepass password -keystore path_to_keystore/name_for_keystore.keystore
-alias 表示证书的别名,一个keystore文件中可以存放多个alias。
-keyalg RSA 表示密钥算法的名称为RSA算法
-keypass password表示密钥的口令是password
-storepass password表示密钥库(生成的keystore文件)的密钥是keypass。
注意:keypass和storepass理论上是可以不同的,但是我们生成的密钥是要给tomcat用的,tomcat这家伙好像没有提供提取私钥的密码(就是上边那个keypass)配置,因此我们只好将两个密码设置成一样的。
-keystore是生成的或者已有的keystore文件的位置,如果不提供的话,keytool工具会把它放在用户目录下,还起了个名字叫.keystore。
配置Tomcat
在Tomcat安装目录的conf文件夹下有个server.xml文件,找到我们需要打开HTTPS功能的Service,添加一个Connector.Tomcat8中给出了一个默认的Connector,我们只需要把它的注释去掉就可以了。
port 端口
protocol 协议.原来低版本的Tomcat版本有可能是”HTTP/1.1”,但是在8这个版本中是一个代表了协议的类.你的是哪个版本就用哪种表述,关键看原来的server.xml所给的例子。
clientAuth 如果设为true,表示Tomcat要求所有的SSL客户出示安全证书,对SSL客户进行身份验证
sslProtocol 指定套接字(Socket)使用的加密/解密协议,默认值为TLS,用户不应该修改这个默认值。
keystoreFile 我们刚生成的那个keystore文件.(可以是绝对/相对路径).如果此项没有设定,Tomcat将从当前操作系统用户的用户目录下读取名为“.keystore”的文件。
keystorePass 我们刚在生成keystore文件的时候所指定的storepass或keypass(它们是一样的,原因前边说啦).指定keystore的密码,如果此项没有设定,在默认情况下,Tomcat将使用“changeit”作为默认密码。
ciphers 指定套接字可用的用于加密的密码清单,多个密码间以逗号(,)分隔。如果此项没有设定,在默认情况下,套接字可以使用任意一个可用的密码。
OK,现在重启你的tomcat,输入地址,把端口改成8443,应该就可以访问了。
一个例子:
http自动跳转https的安全配置
到conf目录下的web.xml。在 后面, 之前,也就是倒数第二段里,加上这样一段:
这步目的是让非ssl的connector跳转到ssl的connector去。所以还需要前往server.xml进行配置:
redirectPort改成ssl的connector的端口443,重启tomcat后便会生效。
以上是权威证书的https配置方法。
最后附上使用jdk的keytool工具生成自签发证书及认证过程(单向和双向认证都能通):https://www.cnblogs.com/longLifeFrog/p/9069715.html
tomcat 禁用目录列表
在{tomcat_home}/conf/web.xml中,把listings参数设置成false即可,如下:
...
...
tomcat限制IP访问
http://www.linuxso.com/linuxrumen/14414.html
如果是apache-tomcat-7.0.20.tar.gz
jdk1.7.0
在:server.xml内的 host标签内增加:
也就是说多个IP或IP段时, 中间以||分隔开。而不是用“,”隔开
应该是版本的问题,其他低版本的是“,”分隔;