文章目录
-
-
- 一、Tomcat性能优化
-
- application.yml配置
- [maxThreads 连接数限制](#maxThreads 连接数限制)
- 压缩传输
- AJP禁用
- 二、JVM方向优化
- 三、Tomcat安全配置
- 四、Tomcat资源控制
- 五、Tomcat运行模式
- 六、总结
-
在现代Web应用中,Tomcat作为Java Servlet容器的代表之一,大部分公司以及学校接触的比较多。同时,Undertow作为另一种流行的Java Web服务器,与Tomcat相比也具有其独特的优势和特点,在一些场景下可以考虑用Undertow。
一、Tomcat性能优化
application.yml配置
可以参考以下的配置文件,为了让大家通俗易懂,都写在注释
里了,针对这些参数调整可以调整为自己合适的数值
js
server:
port: 8080
connection-timeout: 20000 //客户端连接超时时间(以毫秒为单位)
tomcat:
//调整Spring Boot,Spring Cloud 应用中Tomcat连接设置可以改善 Tomcat 处理传入连接的方式。
max-connections: 10000 //可处理的最大连接数
accept-count: 1000 //传入连接请求的最大队列长度
threads:
//调整Spring Boot,Spring Cloud 应用中Tomcat可用的线程数可以帮助有效地处理更多并发请求。
max: 200 //池中最大线程数
min-spare: 10 //最小空闲线程数
//调整Spring Boot,Spring Cloud 应用中Tomcat保持活动设置可以帮助更有效地管理连接。
keep-alive-timeout: 10000 //保持连接超时时间(以毫秒为单位)
max-keep-alive-requests: 100 //可通过保持连接发送的最大请求
//启用压缩可以减少通过网络发送的数据量,从而缩短响应时间。
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain //启用压缩的输出内容大小
min-response-size: 1024 //压缩类型
//配置访问日志可以帮助监控和分析请求模式。
accesslog:
enabled: true
directory: /var/log/tomcat
prefix: access_log
suffix: .txt
//Spring Boot,Spring Cloud应用程序警用优化。例如,禁用不必要的自动配置可以节省资源。
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration
maxThreads 连接数限制
上面配置文件中的maxThreads 是 Tomcat 所能接受最大连接数。一般设置不要超过8000
以上,一般在公司当中如果访问量很大的话可以配置多个tomcat,然后用nginx去进行负载
sh
maxThreads="2048"
压缩传输
上面配置文件中的compression用起来的时候有一些需要注意的地方,压缩会增加Tomcat负担,最好采用Nginx + Tomcat 或者 Apache + Tomcat 方式,压缩交由Nginx/Apache 去做。
sh
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain
min-response-size: 1024
AJP禁用
AJP(Apache JServ Protocol)是一个面向包的协议,用于Web服务器与Servlet容器之间的通信。AJP协议通过TCP连接在Web服务器和Servlet容器之间传递请求和响应,为了节省SOCKET创建的昂贵代价,Web服务器会维持一个长期的TCP连接来重用,这样可以减少建立和拆除连接的开销。,登录完tomcat会看到
因为现在大家都在用Nginx+Tomcat的架构,所以可以通过配置文件来进行禁用
sh
<!-- 禁用AJP连接 -->
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
二、JVM方向优化
设置并行垃圾回收器
在/bin/catalina.sh文件第一行添加如下参数,gc日志输出到/logs/gc.log
sh
#年轻代、老年代均使用并行收集器,初始堆内存64M,最大堆内存512M
JAVA_OPTS="-XX:+UseParallelGC -XX:+UseParallelOldGC -Xms64m -Xmx512m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log"
查看gc日志文件
将gc.log文件上传到gceasy.io查看gc中是否存在问题。上传文件后需要等待一段时间,需要耐心等待。
这里会看到一些吞吐信息,以及gc的情况,年轻代老年代的gc次数,可以根据这些信息来调整内存等一些配置,配置完可以再次测试来看一下是否有所提升
这里是自测的最佳配置仅供参考
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"
参数说明:
file.encoding 默认文件编码
-Xmx1024m 设置JVM最大可用内存为1024MB
-Xms1024m 设置JVM最小内存为1024m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-XX:NewSize 设置年轻代大小
-XX:MaxNewSize 设置最大的年轻代大小
-XX:PermSize 设置永久代大小
-XX:MaxPermSize 设置最大永久代大小
-XX:NewRatio=4 设置年轻代(包括Eden和两个Survivor区)与终身代的比值(除去永久代)。设置为4,则年轻代与终身代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:MaxTenuringThreshold=0 设置垃圾最大年龄,默认为:15。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
-XX:+DisableExplicitGC 这个将会忽略手动调用GC的代码使得System.gc()的调用就会变成一个空调用,完全不会触发任何GC。
在每调一个参数的时候,都可以使用jmeter进行压测,这里不详细说明如何使用了,有兴趣的可以看一下【Jmeter】压力测试工具下载、安装、配置环境变量、中文设置、压测实战教程(超详细)
三、Tomcat安全配置
入侵防范
不要让连接器(connector)监听服务器上所有可用的网络接口和IP地址,而要让连接器监听指定的网络接口和IP地址采用address属性,防止应用程序意外地运行在某个开放的网络接口上。
sh
#将默认值20000改成10000即可单位ms注意需要根据实际需求更改
$vim conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="10000"
redirectPort="8443" address="127.0.0.1" />
禁用非法HTTP请求方法
readonly参数默认是true即不允许delete和put操作编辑,web.xml文件查看org.apache.catalina.servlets.DefaultServlet是否存在如下配置
sh
$vim conf/web.xml
<init-param>
<param-name>readonly</param-name>
<param-value>true</param-value>
</init-param>
禁止目录列出
设置DefaultServlet的listings为false,这不仅仅是因为允许显示目录列表被认为是不安全的,而且还因为生成具有数千个文件的目录列表会消耗大量的CPU资源,相当于被DDoS攻击
sh
$vim conf/web.xml
<!-- 同样也是在下面进行添加-->
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
小知识:DDoS攻击是一种分布式拒绝服务攻击(Distributed Denial of Service Attack)是一种通过向目标系统发送大量的网络流量导致目标系统无法提供正常服务的攻击方式。
防止恶意关闭服务
编辑tomcat配置文件conf/server.xml配置文件,shutdown的值为复杂的字符串
sh
#随机生成密码
$cat /dev/urandom | tr -dc '_a-zA-Z0-9' | head -c 12
r02BPRnHyq89
#配置如下:将默认的SHUTDOWN变成r02BPRnHyq89
<Serverport="8005" shutdown="r02BPRnHyq89">
#如果不需要该功能,必须要将其停用,设置如下:
<Server port="-1" shutdown="SHUTDOWN"> #本地管理脚本可将服务器关闭,即使在关闭端口被禁用的情况下。
配置HTTPS加密协议
采用HTTPS协议加密可以防止中间人攻击,以及数据的拦截和修改的验证导致攻击无效;
使用keytool
生成证书:
sh
#(1)用JDK自带的keytool工具生成一个证书,默认三个月的有效期;
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA -keystore /tmp/keystore
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: Tomcat
What is the name of your organizational unit?
[Unknown]: CQ
What is the name of your organization?
[Unknown]: CQ
What is the name of your City or Locality?
[Unknown]: BEIJING
What is the name of your State or Province?
[Unknown]: XIZHIMEN
What is the two-letter country code for this unit?
[Unknown]: 408119
Is CN=Tomcat, OU=CQ, O=CQ, L=BEIJING, ST=XIZHIMEN, C=408119 correct?
[no]: Y
Enter key password for <tomcat>
(RETURN if same as keystore password):
Re-enter new password:
#(2)修改tomcat安装目录下/conf/server.xml配置文件,更改为使用HTTPS方式,增加如下行:
<Connector classname="org.apache.catalina.http.HttpConnector"
port="443" protocol="HTTP/1.1" minProcessors="5"
SSLEnabled="true"
maxprocessors="100"
enableLookups="true" acceptCount="10" debug="0"
scheme="https"
Factory_classname="org.apache.catalina.SSLServerSocketFactory"
secure="true"
clientAuth="false"
keystoreFile="/tmp/keystore"
keystorePass="weiyigeek"
sslProtocol="TLS" />
#SSL Connector来指定可用的SSL加密方式:
ciphers="SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"
HttpOnly标记
对会话cookie自动启用HttpOnly的cookie标记,查看配置以确保该选项为被禁用。如果应用程序需要通过JavaScript访问HttpOnly cookie,可以在METAINF/context.xml中一个单独的Context中定义一个异常。
sh
#要启用HttpOnly设置使之全局应用于所有应用程序:
<Context useHttpOnly='true'>
...
<Context>
安全头配置
XSS保护:
xml
<filter>
<filter-name>XSSFilter</filter-name>
<filter-class>com.example.XSSFilter</filter-class>
</filter>
防止点击劫持:
xml
<filter>
<filter-name>ClickjackingFilter</filter-name>
<filter-class>com.example.ClickjackingFilter</filter-class>
</filter>
四、Tomcat资源控制
默认程序
${tomcat_home}/webapps中所有的默认的web应用程序有:ROOT、Documentation、Examples、Host Manager和Manager
sh
#如果不是一定需要,可以将它们移除。
rm -rf /opt/tomcat/apache-tomcat-8.5.45/webapps/*
错误页面重定向
编辑tomcat配置文件/conf/web.xml文件,在最后一行之前加入以下内容,然后需要重新启动tomcat服务;
sh
<error-page>
<!-- 配置实现了将404未找到jsp网页的错误导向noFile.htm页面,还可以添加其多的错误代码导向页面,如403,500 -->
<error-code>404</error-code>
<location>/noFile.htm</location>
</error-page>
<error-page>
<!--配置实现了当jsp网页出现java.lang.NullPointerException导常时,转向error.jsp错误页面 -->
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error.jsp</location>
</error-page>
当出现NullPointerException异常时tomcat会把网页导入到error.jsp,且会打印出出错信息。
sh
<%@ pageerrorPage="/error.jsp" %>
典型的error.jsp错误页面的程序写法如下:
<%@ pagecontentType="text/html;charset=GB2312"%>
<%@ pageisErrorPage="true"%>
<html>
<head>
<title>错误页面</title>
</head>
<body>出错了:</p>错误信息:<%= exception.getMessage() %>
<br>
Stack Trace is :
<pre>
<font color="red"><%
java.io.CharArrayWritercw = new java.io.CharArrayWriter();
java.io.PrintWriterpw = new java.io.PrintWriter(cw,true);
exception.printStackTrace(pw);
out.println(cw.toString());
%>
</font>
</pre>
</body>
</html>
注:如果Manager应用程序没被移除,必须手动将位于 CATALINA_HOME/webapps/manager/WEB-INF/jsp/ 的错误页面里的Tomcat版本信息移除。
会话超时
所有的web应用程序的会话超时必须设置为20分钟可通过编辑 CATALINA_HOME/conf/web.xml 文件并做以下配置来实现
sh
<!-- Tomcat8默认的超时时间是半个小时 -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
五、Tomcat运行模式
-
BIO(Blocking I/O) :这是传统的阻塞 I/O 模式。在这种模式下,每个请求都会占用一个线程,这个线程在等待 I/O 操作完成时会被阻塞。
性能低下
-
NIO(Non-blocking I/O) : 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操作(bio)更好的并发运行性能。Tomcat8默认使用nio运行模式。
默认运行模式
-
APR(Apache Portable Runtime) :APR 模式使用 Apache Portable Runtime 库来提供高效的 I/O 操作。APR 从操作系统级别来解决异步的IO问题,大幅度的提高性能。
安装起来最困难
六、总结
如果不管怎么优化都无法突破瓶颈,可以从根本解决问题,不用tomcat,可以考虑以下Undertow
等一些其他的容器来进行本质上的提升