【JAVA】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运行模式

  1. BIO(Blocking I/O) :这是传统的阻塞 I/O 模式。在这种模式下,每个请求都会占用一个线程,这个线程在等待 I/O 操作完成时会被阻塞。性能低下

  2. 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运行模式。默认运行模式

  3. APR(Apache Portable Runtime) :APR 模式使用 Apache Portable Runtime 库来提供高效的 I/O 操作。APR 从操作系统级别来解决异步的IO问题,大幅度的提高性能。安装起来最困难

六、总结

如果不管怎么优化都无法突破瓶颈,可以从根本解决问题,不用tomcat,可以考虑以下Undertow 等一些其他的容器来进行本质上的提升

相关推荐
WaaTong12 分钟前
《重学Java设计模式》之 原型模式
java·设计模式·原型模式
m0_7430484412 分钟前
初识Java EE和Spring Boot
java·java-ee
AskHarries14 分钟前
Java字节码增强库ByteBuddy
java·后端
小灰灰__34 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭38 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果1 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林1 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
duration~2 小时前
Maven随笔
java·maven
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql