目 录CONTENT

文章目录

Tomcat优化

简中仙
2023-05-25 / 0 评论 / 0 点赞 / 40 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2023-11-05,若内容或图片失效,请留言反馈。 本文如有错误或者侵权的地方,欢迎您批评指正!

一、Tomcat 启动优化

如果 Tomcat 启动比较慢,可以考虑一些优化点

1、清理 Tomcat

  • 清理不必要的 Web 应用:首先我们要做的是删除掉 webapps 文件夹下不需要的工程,一般是 host-manager、example、doc 等这些默认的工程,可能还有以前添加的但现在用不着的工程,最好把这些全都删除掉。
rm -rf webapps/*
  • 清理 XML 配置文件:Tomcat 在启动时会解析所有的 XML 配置文件,解析 XML 较为耗时,所以应该尽量保持配置文件的简洁。
  • 清理 JAR 文件:JVM 的类加载器在加载类时,需要查找每一个 JAR 文件,去找到所需要的类。如果删除了不需要的 JAR 文件,查找的速度就会快一些。这里请注意:Web 应用中的 lib 目录下不应该出现 Servlet API 或者 Tomcat 自身的 JAR,这些 JAR 由 Tomcat 负责提供。
  • 清理其他文件:及时清理日志,删除 logs 文件夹下不需要的日志文件。同样还有 work 文件夹下的 catalina 文件夹,它其实是 Tomcat 把 JSP 转换为 Class 文件的工作目录。有时候我们也许会遇到修改了代码,重启了 Tomcat,但是仍没效果,这时候便可以删除掉这个文件夹,Tomcat 下次启动的时候会重新生成。

2、禁止 Tomcat TLD 扫描

Tomcat 为了支持 JSP,在应用启动的时候会扫描 JAR 包里面的 TLD 文件,加载里面定义的标签库。所以在 Tomcat 的启动日志里,你可能会碰到这种提示:

At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

Tomcat 的意思是,我扫描了你 Web 应用下的 JAR 包,发现 JAR 包里没有 TLD 文件。我建议配置一下 Tomcat 不要去扫描这些 JAR 包,这样可以提高 Tomcat 的启动速度,并节省 JSP 编译时间。

如何配置不去扫描这些 JAR 包呢,这里分两种情况:

  • 如果你的项目没有使用 JSP 作为 Web 页面模板,而是使用 Velocity 之类的模板引擎,你完全可以把 TLD 扫描禁止掉。方法是,找到 Tomcat 的conf/目录下的context.xml文件,在这个文件里 Context 标签下,加上JarScannerJarScanFilter子标签,像下面这样。

    <Context>
       <JarScanner >
          <JarScanFilter defaultTldScan="true" defaultpluggabilityScan="true" />
       </JarScanner>
    </Context>
    
  • 如果你的项目使用了 JSP 作为 Web 页面模块,意味着 TLD 扫描无法避免,但是我们可以通过配置来告诉 Tomcat,只扫描那些包含 TLD 文件的 JAR 包。方法是,找到 Tomcat 的conf/目录下的catalina.properties文件,在这个文件里的 jarsToSkip 配置项中,加上你的 JAR 包。

    tomcat.util.scan.StandardJarScanFilter.jarsToSkip=xxx.jar
    

3、关闭 WebSocket 支持

Tomcat 会扫描 WebSocket 注解的 API 实现,比如 @ServerEndpoint 注解的类。如果不需要使用 WebSockets 就可以关闭它。具体方法是,找到 Tomcat 的 conf/ 目录下的 context.xml 文件,给 Context 标签加一个 containerSciFilter 的属性:

<Context containerSciFilter="org.apache.tomcat.websocket.server.WsSci">
...
</Context>

更进一步,如果你不需要 WebSockets 这个功能,你可以把 Tomcat lib 目录下的 websocket-api.jartomcat-websocket.jar 这两个 JAR 文件删除掉,进一步提高性能。

4、关闭 JSP 支持

如果不需要使用 JSP,可以关闭 JSP 功能:

<Context containerSciFilter="org.apache.jasper.servlet.JasperInitializer">
...
</Context>

如果要同时关闭 WebSocket 和 Jsp,可以这样配置:

<Context containerSciFilter="org.apache.tomcat.websocket.server.WsSci | org.apache.jasper.servlet.JasperInitializer">
...
</Context>

5、禁止扫描 Servlet 注解

Servlet 3.0 引入了注解 Servlet,Tomcat 为了支持这个特性,会在 Web 应用启动时扫描你的类文件,因此如果你没有使用 Servlet 注解这个功能,可以告诉 Tomcat 不要去扫描 Servlet 注解。具体配置方法是,在你的 Web 应用的web.xml文件中,设置<web-app>元素的属性metadata-complete="true",像下面这样。

<web-app metadata-complete="true">
</web-app>

metadata-complete 的意思是,web.xml 里配置的 Servlet 是完整的,不需要再去库类中找 Servlet 的定义。

6、配置 Web-Fragment 扫描

Servlet 3.0 还引入了“Web 模块部署描述符片段”的 web-fragment.xml,这是一个部署描述文件,可以完成 web.xml 的配置功能。而这个 web-fragment.xml 文件必须存放在 JAR 文件的 META-INF 目录下,而 JAR 包通常放在 WEB-INF/lib 目录下,因此 Tomcat 需要对 JAR 文件进行扫描才能支持这个功能。

可以通过配置 web.xml 里面的 <absolute-ordering> 元素直接指定了哪些 JAR 包需要扫描 web fragment,如果 <absolute-ordering/> 元素是空的, 则表示不需要扫描,像下面这样。

<web-app metadata-complete="true">
...
<absolute-ordering />
...
</web-app>

7、随机数熵源优化

Tomcat 7 以上的版本依赖 Java 的 SecureRandom 类来生成随机数,比如 Session ID,Linux或者部分unix系统提供随机数设备是/dev/random 和/dev/urandom ,两个有区别,urandom安全性没有random高,但random需要时间间隔生成随机数。。而 JVM 默认使用阻塞式熵源(/dev/random), 在某些情况下就会导致 Tomcat 启动变慢。当阻塞时间较长时, 你会看到这样一条警告日志:

<DATE> org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [8152] milliseconds.

解决方案是通过设置,让 JVM 使用非阻塞式的熵源。

我们可以设置 JVM 的参数:

-Djava.security.egd=file:/dev/./urandom

或者是设置 java.security 文件,位于 $JAVA_HOME/jre/lib/security 目录之下: securerandom.source=file:/dev/urandom

# find / -name "java.security"
/usr/src/jdk1.8.0_261/jre/lib/security/java.security
# vim /usr/src/jdk1.8.0_261/jre/lib/security/java.security
 150 securerandom.source=file:/dev/urandom

8、并行启动多个 Web 应用

Tomcat 启动的时候,默认情况下 Web 应用都是一个一个启动的,等所有 Web 应用全部启动完成,Tomcat 才算启动完毕。如果在一个 Tomcat 下有多个 Web 应用,为了优化启动速度,你可以配置多个应用程序并行启动,可以通过修改 server.xml 中 Host 元素的 startStopThreads 属性来完成。startStopThreads 的值表示你想用多少个线程来启动你的 Web 应用,如果设成 0 表示你要并行启动 Web 应用,像下面这样的配置。

<Engine startStopThreads="0">
    ...
    <Host startStopThreads="0">
        ...
    </Host>
    ...
</Engine>

需要注意的是,Engine 元素里也配置了这个参数,这意味着如果你的 Tomcat 配置了多个 Host(虚拟主机),Tomcat 会以并行的方式启动多个 Host。

9、catalina.sh脚本优化

在注释后的第一行添加以下代码

vim bin/catalina.sh
JAVA_OPTS="-server -Dfile.encoding=UTF-8 -XX:+UseG1GC -XX:MaxTenuringThreshold=14 -Xms1400M -Xmx1400M -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=256m -XX:ConcGCThreads=2 -XX:+AlwaysPreTouch"

二、server.xml优化

建议更改默认8080端口

vim conf/server.xml
    # 删除线程池注释,增加线程池数量
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="500" minSpareThreads="25"/>
    # 原有配置    
    <!--
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    # 注释原有配置,开启带有线程池的配置
    <!-- A "Connector" using the shared thread pool-->
	<Connector executor="tomcatThreadPool"
               port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
               maxSpareThreads="75" enableLookups="false"
               acceptCount="100" debug="0" disableUploadTimeout="true" URIEncoding="UTF-8"
               compression="on" compressionMinSize="2048"
               compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
               connectionTimeout="20000"
               redirectPort="8443" />
    # 禁用AJP连接
    <!--
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               redirectPort="8443" />
    -->           
参数说明
maxThreadsTomcat可创建的最大的线程数,即最大并发数
minSpareThreads最小备用线程数,tomcat 启动时的初始化的线程数
protocol更换nio2运行模式
maxSpareThreads如果空闲状态的线程数多于设置的数目,则将这些线程中止,减少这个池中的线程总数
enableLookups关闭DNS查询
acceptCount线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小,如果这个队列也满了,就直接refuse connection
URIEncoding使得 tomcat 可以解析含有中文名的文件的 url
compression给Tomcat配置gzip压缩(HTTP压缩)功能
compressionMinSize启用压缩的输出内容大小,这里面默认为2KB
compressableMimeType压缩类型
noCompressionUserAgents对于以下的浏览器,不启用压缩

三、安全加固

1、隐藏版本号

默认报错页面信息会暴露出版本号

进入tomcat的lib目录找到catalina.jar文件

cd lib/
unzip catalina.jar
vim org/apache/catalina/util/ServerInfo.properties
server.info=Apache Tomcat
server.number=0.0.0.0
server.built=Sep 23 2022 11:22:29 UTC
jar uvf catalina.jar org/apache/catalina/util/ServerInfo.properties

重启tomcat

四、HTTPS访问Tomcat

因为Tomcat作为web服务器本身性能不强,所以这里使用Nginx进行代理,通过nginx采用https,tomcat采用http的方式进行访问

1、Tomcat配置

vim conf/server.xml
		<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
                   maxThreads="48" minSpareThreads="10"
                   enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
                   scheme="https" secure="true" proxyName="www.example.com" proxyPort="443"
                   protocol="org.apache.coyote.http11.Http11NioProtocol"/>

2、Nginx配置

server {
    listen www.example.com:80;
    server_name www.example.com;
 
    listen 443 default ssl http2;
    ssl_certificate     /usr/local/etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /usr/local/etc/nginx/ssl/nginx.key;
 
    ssl_session_timeout  5m;
 
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers   on;

	location / {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://localhost:8090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
}

五、打包和解压war包

1、解压命令

# mkdir /jpress
# mv /jpress.war /jpress
# cd /jpress/
# /usr/src/jdk1.8.0_261/bin/jar -xf jpress.war 
# ls
jpress.war  META-INF  robots.txt  static  templates  WEB-INF

2、打包命令

# /usr/src/jdk1.8.0_261/bin/jar -cfM0 jpress.war ./
# ls
jpress.war  META-INF  robots.txt  static  templates  WEB-INF
0

评论区