- 定义默认页面、页面超时、禁止列出目录
[root@localhost ~]# vi /usr/local/tomcat/conf/web.xml
115 <init-param>
116 <param-name>listings</param-name>
117 <param-value>false</param-value>
118 </init-param>
##禁止列出目录
606 <session-config>
607 <session-timeout>30</session-timeout>
608 </session-config>
## 页面超时
4704 <welcome-file-list>
4705 <welcome-file>index.html</welcome-file>
4706 <welcome-file>index.htm</welcome-file>
4707 <welcome-file>index.jsp</welcome-file>
4708 </welcome-file-list>
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
115 <!-- Define an AJP 1.3 Connector on port 8009
116 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
117 -->
[root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
[root@localhost ~]# netstat -utpln |grep java
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 2354/java
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 2354/java
- 配置网页传输压缩
注:如若有apache、nginx等做代理,tomcat则不必配置传输压缩;
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
69 <Connector port="8080" protocol="HTTP/1.1"
70 connectionTimeout="20000"
71 redirectPort="8443"
72 compression="on" ##开启压缩
73 compressionMinSize="50" ##指定最小的压缩文件,单位是字节
74 noCompressionUserAgents="gozilla, traviata" ##此浏览器类型不进行压缩
75 compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> ##压缩文件的格式
-
tomcat的三种模式切换
-
先了解四个概念:
- 同步:自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写)。
- 异步:委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需要将数据缓冲区地址和大小传给OS(银行卡和密码),OS需要支持异步IO操作API)。
- 阻塞:ATM排队取款,你只能等待(使用阻塞IO时,Java调用会一直阻塞到读写完成才返回)。
- 非阻塞:柜台取款,取个号,然后坐在椅子上做其它事,等号广播会通知你办理,没到号你就不能去,你可以不断问大堂经理排到了没有,大堂经理如果说还没到你就不能去(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成。
-
Java对BIO、NIO、AIO的支持:
- Java BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
- Java NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
- Java AIO(NIO.2):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
-
BIO、NIO、AIO适用场景分析:
-
-
配置
- 模式一 Bio:tomcat 7.0版本以前默认是Bio
- 模式二Nio:tomcat 8.0版本以后默认是Nio,废弃Bio
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" ##更改位置 connectionTimeout="20000" redirectPort="8443" compression="on" compressionMinSize="50" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> [root@localhost bin]# tail -f ../logs/catalina.out ... 22-Aug-2022 22:51:26.479 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
- 模式三Apr:
[root@localhost ~]# rpm -e apr --nodeps [root@localhost ~]# yum -y install apr apr-devel [root@localhost ~]# cp /usr/local/tomcat/bin/tomcat-native.tar.gz /root/ [root@localhost ~]# tar xf tomcat-native.tar.gz [root@localhost ~]# cd tomcat-native-1.2.17-src/native/ [root@localhost native]# ./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/local/java/ [root@localhost native]# make && make install Libraries have been installed in: ##安装成功的提示 /usr/local/apr/lib [root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh ##添加或追加 #!/bin/sh CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib" [root@localhost ~]# vi /usr/local/tomcat/conf/server.xml ##注意需要将https的8443端口配置项删除,不然会导致http端口8080无法启动 <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" compression="on" compressionMinSize="50" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" /> [root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib [root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh [root@localhost ~]# /usr/local/tomcat/bin/startup.sh [root@localhost ~]# netstat -utpln |grep java tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 4859/java tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 4859/java [root@localhost ~]# tail -f ../logs/catalina.out ... 22-Aug-2022 23:10:16.286 信息 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-8080"]
-
解决重启tomcat服务后,8005端口延迟启动的问题
[root@localhost ~]# vi /usr/local/java/jre/lib/security/java.security
17 securerandom.source=file:/dev/urandom
或 117 securerandom.source=file:/dev/./random
[root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
- 生产环境tomcat配置
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
URIEncoding="UTF-8" ##设置编码
maxThreads="300" ##接收客户请求最大线程数,也就是同时处理请求的最大数目,默认值为“200”,并不是配置的越大越好,事实上你即使配置成999999也是没有用的,因为这个最大值是受操作系统及相关硬件所制约的,并且最大值并不一定是最优值,所以我们追寻的应该是最优值而不是最大值。建议值为1000;
QPS(Query Per Second):每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。我们常常使用 QPS值来衡量一个服务器的性能。
QPS = 并发数 / 平均响应时间 或者 并发数 = QPS * 平均响应时间
一个系统吞吐量通常由QPS、并发数两个因素决定,每套系统的这两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换、内存等等其它消耗导致系统性能下降。所谓吞吐量这里可以理解为每秒能处理请求的次数。
所以选择一个合理的 maxThreads值,其实并不是那么容易的事。因为过多的线程只会造成,更多的内存开销,更多的CPU开销,但是对提升QPS确毫无帮助;找到最佳线程数后通过简单的设置,可以让web系统更加稳定,得到最高,最稳定的QPS输出。
通过以下几种方式来获取 maxThreads的最佳值:
(1)通过线上系统不断使用和用户的不断增长来进行性能测试,观察QPS,响应时间,这种方式会在爆发式增长时系统崩溃,如双12等。
(2)根据公式计算,服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量,这种方式有时会被误导,因为某些系统处理环节可能会耗时比较长,从而影响公式的结果。
(3)单、多用户压力测试,查看CPU的消耗,然后直接乘以百分比,再进行压测,一般这个值的附近应该就是最佳线程数量,这种方式理想场景比较适用,实际情况会比这个复杂的多。
(4)根据系统的自身情况调整,如硬件限制,系统限制,程序处理能力限制等。
(5)定期修改为不同的 maxThreads值,看服务器响应结果及用户反应。
QPS和线程数的关系:
(1)在最佳线程数量之前,QPS和线程是互相递增的关系,线程数量到了最佳线程之后,QPS持平,不在上升,甚至略有下降,同时相应时间持续上升。
(2)同一个系统而言,支持的线程数越多(最佳线程数越多而不是配置的线程数越多),QPS越高。
QPS和响应时间的关系:
(1)对于一般的web系统,响应时间一般有CPU执行时间+IO等待时间组成。
(2)CPU的执行时间减少,对QPS有实质的提升,IO时间的减少,对QPS提升不明显。如果要想明显提升QPS,优化系统的时候要着重优化CPU消耗大户。
minSpareThreads="25" ##最小空闲的线程数,Tomcat初始化时创建的 socket线程数,默认为10
maxSpareThreads="75" ##最大空闲线程数,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程。默认值50
enableLookups="false" ##关闭DNS反向查询
disableUploadTimeout="true" ##该标志位表明当执行servlet时,是否允许servlet容器使用一个不同的、更长的连接超时。启用该标志位将导致在上传数据时,要么使用更长的时间完成上传,要么出现更长的超时。如果不指定,该属性为“false”。
connectionTimeout="20000" ##当请求已经被接受,但未被处理,也就是等待中的超时时间。单位为毫秒,默认值为60000。通常情况下设置为30000。
acceptCount="300" ##容许的最大连接的队列长度,一般设置为maxProcessors是其参数的1.5倍即可,默认值为100。此值设置的过大会导致排队的请求超时而未被处理。所以这个值应该是主要根据应用的访问峰值与平均值来权衡配置。
tcpNoDelay="true" ##如果为true,服务器socket会设置TCP_NO_DELAY选项,在大多数情况下可以提高性能。缺省情况下设为true。
maxProcessors="1000" ##并发处理的最大请求数,默认值为75,一旦创建的线程超过这个值,Tomcat就会关闭不再需要的socket线程
<!-- 前端使用nginx作为反向代理,不需要启用tomcat压缩功能。
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
-->
redirectPort="8443" ##开启安全通道ssl
/>
-
JVM内存优化管理;
- JVM内存管理:
JVM管理的内存可以总体划分为两部分:堆内存Heap Memory和非堆内存Native Memory。堆内存Heap Memory:供Java应用的代码使用的;
非堆内存Native Memory:也称为C-Heap,是供JVM自身进程使用的;
Heap Memory及其内部各组成的大小可以通过JVM的一系列命令行参数来控制;
Native Memory没有相应的参数来控制大小,其大小依赖于操作系统进程的最大值; - 为什么会内存溢出:
简单理解java process memory = java heap + native memory。因此内存溢出时,首先要区分是堆内存溢出还是非堆内存溢出;
非堆内存Native Memory本质上就是因为耗尽了进程地址空间。对于HotSpot JVM来说,不断的分配直接内存,会导致如下错误信息:Allocated 1953546760 bytes of native memory before running out; -
调优JVM分配内存数据:
- 堆内存分配:
JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;
JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4;
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制;
因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小;
说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemoryError: Heap space错误; - 非堆内存分配:
JVM使用-XX:PermSize= 设置非堆内存初始值,默认是物理内存的1/64;
JVM使用-XX:MaxPermSize= 设置最大非堆内存的大小,默认是物理内存的1/4;
说明:-XX:MaxPermSize= 设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存溢出;
[root@localhost ~]# vi /usr/local/tomcat/bin/catalina.sh #!/bin/sh JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=512m" 注解: -Xms初始堆内存Heap大小,使用的最小内存,cpu性能高时此值应设的大一些; -Xmx初始堆内存heap最大值,使用的最大内存; -XX:PermSize= 设定非堆内存的初始内存大小; -XX:MaxPermSize= 设定非堆内存最大值内存大小; -XX:NewSize= 设置Yong Generation的初始值大小; -XX:MaxNewSize=设置Yong Generation的最大值大小; -Xss15120这使得Tomcat每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k;
- 堆内存分配:
- JVM内存管理:
-
Executor线程池优化管理;
- 概述:Executor代表了一个线程池,可以在Tomcat组件之间共享。使用线程池的好处在于减少了创建销毁线程的相关消耗,而且可以提高线程的使用效率。
- 配置管理线程池:
[root@localhost ~]# vi /usr/local/tomcat/conf/server.xml 53 <Service name="Catalina"> 54 <Executor name="tomcatThreadPool" 55 namePrefix="catalina-exec-" 56 maxThreads="1000" 57 minSpareThreads="100" 58 maxIdleTime="60000" 59 maxQueueSize="Integer.MAX_VALUE" 60 prestartminSpareThreads="false" 61 threadPriority="5" 62 className="org.apache.catalina.core.StandardThreadExecutor"/> [root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh [root@localhost ~]# /usr/local/tomcat/bin/startup.sh #注解: name:线程池名称,用于 Connector中指定。 namePrefix:所创建的每个线程的名称前缀,单独的线程名称为 namePrefix+threadNumber。 maxThreads:池中最大线程数。 minSpareThreads:活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。 maxIdleTime:线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。 maxQueueSize:在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值不需要更改,否则会有请求不会被处理的情况发生。 prestartminSpareThreads:启动线程池时是否启动。 minSpareThreads部分线程。默认值为false,即不启动。 threadPriority:线程池中线程优先级,默认值为5,值从1到10。 className:线程池实现类,未指定情况下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。如果想使用自定义线程池首先需要实现 org.apache.catalina.Executor接口。