Tomcat优化
官方文档
https://tomcat.apache.org/tomcat-8.0-doc/config/http.html
https://tomcat.apache.org/tomcat-8.0-doc/config/ajp.html
http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html
由Server.xml的结构看Tomcat的体系结构
<Server> //顶层类元素,可以包括多个Service
<Service> //顶层类元素,可包含一个Engine,多个Connecter
<Connector> //连接器类元素,代表通信接口
<Engine> //容器类元素,为特定的Service组件处理客户请求,要包含多个Host
<Host> //容器类元素,为特定的虚拟主机组件处理客户请求,可包含多个Context
<Context> //容器类元素,为特定的Web应用处理所有的客户请求
</Context>
</Host>
</Engine>
</Connector>
</Service>
</Server>
图形界面管理
#文件位置:C:\Program Files\apache-tomcat-8.5.51\conf\tomcat-users.xml
#44行添加
<role rolename="manager"/>
<role rolename="manager-gui"/>
<role rolename="admin"/>
<role rolename="admin-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user username="admin" password="password" roles="admin-gui,admin,manager-gui,manager,manager-script,manager-jmx,manager-status"/>
#重启tomcat
#浏览器访问:http://localhost:8080/manager/status;用户名:admin;密码:password
1.Windows安装启动tomcat8.5,日志输出乱码
#安装位置:C:\Program Files\apache-tomcat-8.5.51\bin
#配置修改:C:\Program Files\apache-tomcat-8.5.51\conf\logging.properties
#48行添加下面一行
java.util.logging.ConsoleHandler.encoding = GBK
#参考:
https://blog.csdn.net/weixin_38860401/article/details/88059360
2.服务排错
#检查jdk
C:\>java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
#检查端口
C:\Users\18620>netstat -a
C:\Program Files\apache-tomcat-8.5.51\conf\server.xml
3.配置项的删除
C:\Program Files\apache-tomcat-8.5.51\conf\web.xml
DefaultServlet
这是一个处理静态文件的servlet,如果项目中不需要tomcat进行静态文件的处理,可以将其删掉
#113行
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
JspServlet
这个servlet是用来编译和执行jsp文件的,如果项目中没有jsp文件,可以将其删掉
#261行
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
jsp
项目中没有jsp,关于jsp下面的映射也可以删除
#435行
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
mime
文件中提供的mime类型非常多,如果有确定项目中不会涉及到的类型,可以删除其映射配置
#640行
<mime-mapping>
<extension>123</extension>
<mime-type>application/vnd.lotus-1-2-3</mime-type>
</mime-mapping>
<mime-mapping>
...
<mime-mapping>
<extension>zmm</extension>
<mime-type>application/vnd.handheld-entertainment+xml</mime-type>
</mime-mapping>
welcome-file-list
如果不需要展示tomcat的欢迎页,可以将其删掉
#4725行
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
C:\Program Files\apache-tomcat-8.5.51\conf\server.xml
VersionLoggerListener
在Tomcat初始化时,打印一下Tomcat相关的版本信息以及操作系统和jdk环境信息,可以删掉
AprLifecycleListener
Tomcat启动时,检查APR库,如果存在则加载,这个配置仅当connector的protocol设置为AJP/1.3时有用,如果非AJP/1.3,可以删除
JreMemoryLeakPreventionListener
Java运行环境可能导致某些已知位置的内存泄漏或文件锁定,JreMemoryLeakPreventionListener提供这些情况的解决方案
GlobalResourcesLifecycleListener
作用于全局资源,通过该监听器,初始化标签中定义的全局JNDI资源;如果没有该监听器,定义的全局资源都不能使用如果不使用GlobalNamingResources定义全局资源,可以删除
ThreadLocalLeakPreventionListener
Web应用因thread-local导致的内存泄露而要停止时,该监听器会触发线程池中线程的更新只有当Web应用(即Context元素)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效
#23行
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
GlobalNamingResources
定义全局资源,通过读取$TOMCAT_HOME/ conf/tomcat-users.xml实现的tomcat-user.xml用于定义tomcat管理页面相关配置,如果不登录管理界面可以删掉
#37行
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
Connector
当tomcat需要集成到Apache服务器时才使用这个connector,现在一般都用Nginx代替Apache,所以不使用Apache的话这个也可以删掉
2020年02月20日 CNVD披露 AJP 协议漏洞,可以直接注释或删除
#115行
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
-->
Realm
可以把它理解成“域”;Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用,tomcat默认的这个realm是和name为UserDatabase的资源绑定的,而该资源在Server元素中使用GlobalNamingResources配置如果不需要可以删掉
#143行
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
Valve
意思是“阀门”,不同的Valve有不同的特性,AccessLogValve的作用是记录其所在容器处理的所有请求,默认配置中的Valve放在Host下,便可以记录该Host处理的所有请求AccessLogValve记录的日志就是访问日志,每天的请求会写到一个日志文件里现在一般记录Nginx访问日志,这个也可以删除
#161行
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
4.配置参数的修改
server
port:指定一个端口,这个端口负责监听关闭tomcat的请求
shutdown:指定向端口发送的命令字符串
#22行
<Server port="8005" shutdown="SHUTDOWN">
...
service
name:指定service的名字
#53行
<Service name="Catalina">
...
Engine
name:属性用于日志和错误信息,在整个Server中应该唯一
defaultHost:defaultHost属性指定了默认的host名称,当发往本机的请求指定的host名称不存在时,一律使用defaultHost指定的host进行处理;因此defaultHost的值,必须与Engine中的一个Host组件的name属性值匹配
#132行
<Engine name="Catalina" defaultHost="localhost">
Realm
存放用户名,密码及role的数据库
className:指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口
#143行
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
Valve
功能与Logger差不多,其prefix和suffix属性解释和Logger 中的一样
className:规定了Valve的类型;例如tomcat默认的是AccessLogValve
directory:指定日志存储的位置,默认日志存储在$TOMCAT_HOME/logs目录下
prefix:指定了日志文件的前缀
suffix:指定了日志文件的后缀通过directory、prefix和suffix的配置,在$TOMCAT_HOME/logs目录下,可以看到如下所示的日志文件
#164行
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
以上参数暂无可优化
Connector
port:指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求
minProcessors:服务器启动时创建的处理请求的线程数
maxProcessors:最大可以创建的处理请求的线程数
enableLookups:如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址
redirectPort:指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号
acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理
maxConnections:达到这个值之后,将继续接受连接,但是不处理,能继续接受多少根据acceptCount的值
minSpareThreads:最小空闲线程数
connectionTimeout:指定超时的时间数(以毫秒为单位)
#62行
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the
AprLifecycleListener.
Either JSSE or OpenSSL style configuration may be used regardless of
the SSLImplementation selected. JSSE style configuration is used below.
-->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
configuration is used below.
-->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
默认协议使用的是Http11NioProtocol,即NIO方式tomcat默认连接池有限制,可以为connector配置自己的连接池,在连接池中可以根据项目自定义最大线程数量,如:
#56行
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
#74行
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
host
name:指定虚拟主机的主机名,一个Engine中有且仅有一个Host组件的name属性与Engine组件的defaultHost属性相匹配;一般情况下,主机名需要是在DNS服务器中注册的网络名,但是Engine指定的defaultHost不需要
appBase:应用程序基本目录,即存放应用程序的目录
unpackWARs:指定了是否将war文件解压,如果为true,则通过解压后的目录运行该Web应用;如果为false,则直接使用WAR文件运行Web应用
autoDeploy:是否自动部署,Tomcat运行期间会用一个线程定时检查,如果有新的web工程会自动部署
#152行
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
autoDeploy生产环境之下可以改成false,减少tomcat的负担
autoDeploy有需要注意的点,如果为true,拷贝war到webapp下面,tomcat自动解压并部署但是停掉tomcat拷贝新的war包过去,tomcat不会解压新包然后覆盖旧目录,因为tomcat直接使用了之前解压过的目录
Context
docBase:代表应用程序或war文件存放的路径,这个可以自由指定,例如d:/study
path:表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/**
reloadable:如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib和/WEB-INF/classes目录的变化,自动装载新的应用程序,可以在不重起tomcat的情况下改变应用程序
生产环境中可以把reloadable设置为false
#167行
<Context docBase="ROOT" path="/" reloadable="false" sessionCookieName="jxkh"/>
5.jvm参数优化
C:\Program Files\apache-tomcat-8.5.51\bin\catalina.bat
JAVA_OPTS参数说明 :
-server 启用jdk的server版
-Xms java虚拟机初始化时的最小内存;
-Xmx java虚拟机可使用的最大内存;
-XX:PermSize 内存永久保留区域
-XX:MaxPermSize 内存最大永久保留区域tomcat运行在jvm上,垃圾处理方式等都要遵循jvm的方式tomcat中设置jvm参数在 catalina.sh(Linux)和catalina.bat(windows)中,以JAVA_OPTS变量存储以catalina.sh为例:
可以在该变量中添加jvm参数,达到减少gc次数等目标,如根据tomcat所在服务器修改jvm内存大小等
#249行
if [ -z "$JSSE_OPTS" ] ; then
JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
JAVA_OPTS="$JAVA_OPTS -server -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=256 -Djava.awt.headless=true"
fi
未完待续…