网站首页 > 技术文章 正文
目录
- 3. Tomcat 性能调优3.1 Tomcat 性能测试3.2 Tomcat 性能优化3.2.1Tomcat配置调优1.禁用AJP连接2.Connector 连接器的选择3.Executor线程池调整3.2.2 JVM参数调优1) JVM内存参数2) GC策略3.2.3 Tomcat架构调优动静分离:Tomcat集群:修改Tomcat默认端口号tomcat中部署项目的方式
3. Tomcat 性能调优
性能优化的三个指标
降低响应时间 :
提高系统吞吐量(QPS) : QPS (每秒请求量) T(事务) PS (每秒处理事务的数量)
提高服务的可用性:
性能优化的原则
具体情况具体分析
积少成多
性能分析工具
JConsole jvm性能监控平台: 主要监控 内存和CPU的情况
JMeter 分布式性能测试工具: 响应时间、吞吐量、错误率
性能优化测试指标
正确率、CPU占有率、QPS、JVM
3.1 Tomcat 性能测试
我们使用JMeter来进行测试:
3.2 Tomcat 性能优化
3.2.1Tomcat配置调优
1.禁用AJP连接
默认状态下,Tomcat会启动AJP服务,占用8009端口。
AJP是什么?有什么作用呢?
AJP(Apache JServer Protocol) 是为Tomcat与HTTP服务器之间通信而定制的协议,能提供较高的通信速度和效率。
Tomcat虽然是一个javaWeb服务器,可以对静态资源进行解析,但它最主要的作用是提供Servlet 和 Jsp容器,对静态资源的解析肯定不如一些专业的Http服务器 如:apache、nginx 。所以通常生产环境会把Tomcat和其他http服务器搭配使用, 所有请求都访问http服务器,如果访问的资源是Servlet或Jsp则http服务器将请求交由Tomcat处理,如果静态资源 http服务器直接处理, ajp就是apache服务器和tomcat服务器通信的主要协议,nginx 和 浏览器是不支持这个协议的,所以如果你不使用Tomcat和Apache服务器整合的话,这个AJP协议服务是没必要开启的。
ajp就是下面这行代码来配置,主要注释它就可以禁用AJP
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
2.Connector 连接器的选择
Tomcat 连接器的三种方式: bio、nio 和 apr,三种方式性能差别很大,apr 的性能最优, bio 的性能最差。而 Tomcat 7 使用的 Connector 默认就启用的 Apr 协议,但需要系统安装 Apr 库,否则就会使用 bio 方式。
BIO:
一个线程处理一个请求。缺点:并发量高时,线程数较多,浪费资源。
Tomcat7或以下,在Linux系统中默认使用这种方式。
NIO:
利用Java的异步IO处理,可以通过少量的线程处理大量的请求。
Tomcat8在Linux系统中默认使用这种方式。
Tomcat7必须修改Connector配置来启动:
APR:
即Apache Portable Runtime,从操作系统层面解决io阻塞问题。
Tomcat7或Tomcat8在Win7或以上的系统中启动默认使用这种方式。
Linux如果安装了apr和native,Tomcat直接启动就支持apr。
tomcat8 提供了nio2,效率要比nio快些,所以如果是tomcat8之前的版本推荐使用nio ,如果是tomcat8及之后的版本使用nio2
APR( Apache Portable Runtime) 提供卓越的伸缩性,更强的性能以及跟原生服务器技术更好的集成。
如果使用APR要保证1.配置文件中引入了APR的监听 2.服务器上安装APR的相关软件
linux配置APR:
安装依赖
yum install apr-devel yum install openssl-devel yum install gcc yum install make
安装APR包
进入 apache-tomcat-8.5.39/bin 执行命令 tar -xzvf tomcat-native.tar.gz
输入命令 cd tomcat-native-1.2.21-src/native/
进入到native文件夹下
执行命令 ./configure && make && make install
安装后会出现这个界面,表示安装成功,并给出了安装后的目录位置
通过上图我们可以看到 我们还需要配置两个环境变量
输入命令使环境变量生效 source /etc/profile
修改server.xml 配置
启动tomcat查看日志
进入到 /logs目录 执行命令 tail -f -n 200 catalina.out
<Connector executor="tomcatThreadPool"
port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
redirectPort="8443"/>
Connector参数解释
URIEncoding:指定 Tomcat 容器的 URL 编码格式,语言编码格式这块倒不如其它 WEB 服务器软件配置方便,需要分别指定。
面试可以说:设置连接超时时间,当后台出现问题,连接可以及时断掉
connnectionTimeout: 网络连接超时,单位:毫秒,设置为 0 表示永不超时,这样设置有隐患的。通常可设置为 30000 毫秒(30秒),可根据检测实际情况,适当修改。
enableLookups: 是否反查域名,以返回远程主机的主机名,取值为:true 或 false,如果设置为false,则直接返回IP地址,为了提高处理能力,应设置为 false。
disableUploadTimeout:上传时是否使用超时机制。
connectionUploadTimeout:上传超时时间,毕竟文件上传可能需要消耗更多的时间,这个根据你自己的业务需要自己调,以使Servlet有较长的时间来完成它的执行,需要与上一个参数一起配合使用才会生效。
acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可传入连接请求的最大队列长度,超过这个数的请求将不予处理,默认为100个。
keepAliveTimeout:长连接最大保持时间(毫秒),表示在下次请求过来之前,Tomcat 保持该连接多久,默认是使用 connectionTimeout 时间,-1 为不限制超时。
maxKeepAliveRequests:表示在服务器关闭之前,该连接最大支持的请求数。超过该请求数的连接也将被关闭,1表示禁用,-1表示不限制个数,默认100个,一般设置在100~200之间。
面试可以说压缩:连接器参数开启响应数据压缩
compression:是否对响应的数据进行 GZIP 压缩,off:表示禁止压缩;on:表示允许压缩(文本将被压缩)、force:表示所有情况下都进行压缩,默认值为off,压缩数据后可以有效的减少页面的大小,一般可以减小1/3左右,节省带宽。
compressionMinSize:表示压缩响应的最小值,只有当响应报文大小大于这个值的时候才会对报文进行压缩,如果开启了压缩功能,默认值就是2048KB。
compressableMimeType:压缩类型,指定对哪些类型的文件进行数据压缩。
noCompressionUserAgents="gozilla, traviata": 对于以下的浏览器,不启用压缩。
参考配置
连接器的具体参考配置:
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
URIEncoding="UTF-8"
connectionTimeout="30000"
enableLookups="false"
disableUploadTimeout="false"
connectionUploadTimeout="150000"
acceptCount="300"
keepAliveTimeout="120000"
maxKeepAliveRequests="1"
compression="on"
compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png" redirectPort="8443" />
3.Executor线程池调整
默认配置下,Tomcat 会为每个连接器创建一个绑定的线程池(最大线程数 200),服务启动时,默认创建了 5 个空闲线程随时等待用户请求
默认情况:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
修改连接池:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" minSpareThreads="100" maxSpareThreads="50" maxIdleTime="60000"/>
机器比较好情况:最小线程数不超过<100,最大线程数不超过<500
然后,修改<Connector …>节点,增加 executor 属性,调整为
<Connector executor="tomcatThreadPool"
port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
redirectPort="8443"/>
Executor参数解释:
maxThreads,最大并发数,默认设置 200,一般建议在 500 ~ 800,根据硬件设施和业务来判断
minSpareThreads,Tomcat 初始化时创建的线程数,默认设置 25
prestartminSpareThreads,在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值,如果不等于 true,minSpareThreads 的值就没啥效果了
maxQueueSize,最大的等待队列数,超过则拒绝请求
3.2.2 JVM参数调优
Tomcat是一款Java应用,那么JVM的配置便与其运行性能密切相关,而JVM优化的重点则集中在内存分配和GC策略的调整上,因为内存会直接影响服务的运行效率和吞吐量,JVM垃圾回收机制则会不同程度地导致程序运行中断。可以根据应用程序的特点,选择不同的垃圾回收策略,调整JVM垃圾回收策略,可以极大减少垃圾回收次数,提升垃圾回收效率,改善程序运行性能。
1) JVM内存参数
参数 | 参数作用 | 优化建议 |
-server | 启动Server,以服务端模式运行 | 服务端模式建议开启 |
-Xms | 最小堆内存 | 建议与-Xmx设置相同 |
-Xmx | 最大堆内存 | 建议设置为可用内存的80% |
-XX:MetaspaceSize | 元空间初始值 | |
-XX:MaxMetaspaceSize | 元空间最大内存 | 默认无限 |
-XX:NewSize | 新生代初始值 | |
-XX:MaxNewSize | 新生代最大内存 | 默认16M |
-XX:NewRatio | 年轻代和老年代大小比值,取值为整数,默认为2 | 不建议修改 |
-XX:SurvivorRatio | Eden区与Survivor幸存者区大小的比值,取值为整数,默认为8 | 不建议修改 |
-Xms:Java虚拟机初始化时堆的最小内存,一般与 Xmx配置为相同值,这样的好处是GC不必再为扩展内存空间而消耗性能;
可以利用JDK自带的工具进行验证,这些工具都在/bin目录下:
1)jps:用来显示本地的java进程,以及进程号,进程启动的路径等。
2)jmap:观察运行中的JVM 物理内存的占用情况,包括Heap size , Perm size等。
进入命令行模式后,进入JAVA_HOME/bin目录下,然后输入jps命令:
free -m 命令查看当前服务器的可用内存
JAVA_OPTS="-server -Xms2048m -Xmx2048m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -XX:SurvivorRatio=8"
2) GC策略
JVM垃圾回收性能有以下两个主要的指标:
- 吞吐量:工作时间(排除GC时间)占总时间的百分比, 工作时间并不仅是程序运行的时间,还包含内存分配时间。
- 暂停时间:测试时间段内,由垃圾回收导致的应用程序停止响应次数/时间。
不同的应用程序, 对于垃圾回收会有不同的需求。 JVM 会根据运行的平台、服务器资源配置情况选择合适的垃圾收集器、堆内存大小及运行时编译器。如无法满足需求, 参考以下准则:
A. 程序数据量较小,选择串行收集器。
B. 应用运行在单核处理器上且没有暂停时间要求, 可交由JVM自行选择或选择串行收集器。
C. 如果考虑应用程序的峰值性能, 没有暂停时间要求, 可以选择并行收集器。
D. 如果应用程序的响应时间比整体吞吐量更重要, 可以选择并发收集器。
查看Tomcat中的默认的垃圾收集器:
1). 在tomcat/bin/catalina.sh的配置中, 加入如下配置
JAVA_OPTS=" -Djava.rmi.server.hostname=192.168.18.129 -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.rmi.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
2). 打开 jconsole , 查看远程的tomcat的概要信息
连接远程tomcat
GC参数:
参数 | 描述 |
-XX:+UseSerialGC | 启用串行收集器 |
-XX:+UseParallelGC | 启用并行垃圾收集器,配置了该选项,那么 -XX:+UseParallelOldGC默认启用 |
-XX:+UseParallelOldGC | FullGC 采用并行收集,默认禁用。如果设置了 -XX:+UseParallelGC则自动启用 |
-XX:+UseParNewGC | 年轻代采用并行收集器,如果设置了 -XX:+UseConcMarkSweepGC选项,自动启用 |
-XX:+ParallelGCThreads | 年轻代及老年代垃圾回收使用的线程数。默认值依赖于JVM使用的CPU个数 |
-XX:+UseConcMarkSweepGC | 并发垃圾收集器 对于老年代,启用CMS垃圾收集器。 当并行收集器无法满足应用的延迟需求是,推荐使用CMS或G1收集器。 |
-XX:+UseG1GC | 启用G1收集器。 G1是服务器类型的收集器, 用于多核、大内存的机器。它在保持高吞吐量的情况下,高概率满足GC暂停时间的目标。 |
我们也可以在测试的时候,将JVM参数调整之后,将GC的信息打印出来,便于为我们进行参数调整提供依据,具体参数如下:
选项 | 描述 |
-XX:+PrintGC | 打印每次GC的信息 |
-XX:+PrintGCApplicationConcurrentTime | 打印最后一次暂停之后所经过的时间, 即响应并发执行的时间 |
-XX:+PrintGCApplicationStoppedTime | 打印GC时应用暂停时间 |
-XX:+PrintGCDateStamps | 打印每次GC的日期戳 |
-XX:+PrintGCDetails | 打印每次GC的详细信息 |
-XX:+PrintGCTaskTimeStamps | 打印每个GC工作线程任务的时间戳 |
-XX:+PrintGCTimeStamps | 打印每次GC的时间戳 |
在bin/catalina.sh的脚本中 , 追加如下配置 :
JAVA_OPTS="-XX:+UseConcMarkSweepGC -XX:+PrintGCDetails"
64位系统 centos 6.4 内存8G服务器
-server
-Xms6000M
-Xmx6000M
-Xmn500M
-XX:MetaspaceSize=500M
-XX:MaxMetaspaceSize=500M
-XX:SurvivorRatio=65536
-XX:MaxTenuringThreshold=0
-Xnoclassgc
-XX:+DisableExplicitGC
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0
-XX:CMSInitiatingOccupancyFraction=80
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-Xloggc:log/gc.log
3.2.3 Tomcat架构调优
前面我们已经通过系统、jvm、和tomcat自身大大提升的tomcat的性能,但tomcat的性能是有极限的,Tomcat理论支持500左右并发,所以接下来我们会聊聊在如何合理使用tomcat上,实际上也就是架构的 层面聊聊如果优化。这里面我们主要讨论两个优化思路:动静分离、Tomcat集群
就需要搭建Tomcat的集群,而目前比较流程的做法就是通过Nginx来实现Tomcat集群的负载均衡。
动静分离:
Tomcat主要处理servlet、jsp占优势,项目中静态资源(图片、视频、.CSS、.html、.js)访问,耗费请求连接,把静态资源放在Nginx服务器中,静态请求不经过Tomcat,不占并发数。
Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。
优点:
1、可以高并发连接
官方测试Nginx能够支撑5万并发连接,实际生产环境中可以支撑2~4万并发连接数。
2、内存消耗少
Nginx+PHP(FastCGI)服务器,
在3万并发连接下,开启10个Nginx进程消耗150MB内存,15MB*10=150MB,
开启的64个PHP-CGI进程消耗1280内存,20MB*64=1280MB,加上系统自身消耗的内存,
总共消耗不到2GB的内存。
3、成本低廉
购买F5BIG-IP、NetScaler等硬件负载均衡交换机,需要十多万到几十万人民币,而Nginx为开源软件,采用的是2-clause BSD-like协议,可以免费试用,并且可用于商业用途。
4、配置文件非常简单
网络和程序一样通俗易懂,即使,非专用系统管理员也能看懂。
5、内置的健康检查功能
如果NginxProxy后端的某台Web服务器宕机了,不会影响前端的访问。
6、节省带宽
支持GZIP压缩,可以添加浏览器本地缓存的Header头。
7、稳定性高
用于反向代理,宕机的概率微乎其微。
8、支持热部署
Nginx支持热部署,它的自动特别容易,并且,几乎可以7天*24小时不间断的运行,即使,运行数个月也不需要重新启动,还能够在不间断服务的情况下,对软件版本进行升级。
Nginx反向代理配置:
Tomcat集群:
大佬参考地址:https://www.cnblogs.com/liaokailin/p/3968891.html
修改Tomcat默认端口号
tomcat默认的端口号(缺省端口),怎么修改
tomcat默认的端口是8080
修改Server.xml中 Connector的port属性即可,
如果同一个tomcat要启动多个tomcat ,还需要修改Server里面的port端口 以及Connector AJP协议的port端口
<Server port="8006" shutdown="SHUTDOWN">
<Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol" redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
tomcat中部署项目的方式
部署的三种方案:
1.直接将web项目 或 war包 拷贝至webapps目录下即可:
2.在配置文件Server.xml中找到标签,在里面 加上下面一句:
<Context docBase="项目的路径" path="虚拟目录" />
3.conf/Catalina/localhost 创建 xxx.xml文件,在文件中指定项目路径,该项目的访问路径 即文件的名字
<Context docBase="项目的路径" />
PS:ROOT文件夹内是根目录下的项目,访问该项目不需要加虚拟目录
tomcat中运行的生产项目,出现问题如何排查?
出现问题首先去tomcat的logs目录下,查看日志文件中有没有什么错误信息。
catalina.201X-XX-XX.log记录启动时日志信息
localhost.201X-XX-XX.log记录各个webapp下项目的日志信息
tail -f fileName
#会把 filename 文件里的最尾部的内容显示在屏幕上,并且不断刷新,只要 filename 更新就可以看到最新的文件内容。
如:日志中发现
java.lang.StackOverflowError异常,这个是栈内存溢出
可能在哪些地方发生内存泄漏了,如果通过异常能够找到溢出的发生地,则优化对应代码。
如果没有发现,则可以通过 JvisualVM 等工具监控Tomcat的运行情况
学习更多JAVA知识与技巧,关注与私信博主(学习)免费学习领取JAVA 课件,源码,安装包,还有最新
大厂面试资料等等等
猜你喜欢
- 2024-10-21 数据库同步 Elasticsearch 后数据不一致,怎么办
- 2024-10-21 (建议收藏)小白视角总结分布式搜索组件elasticsearch《二》
- 2024-10-21 RabbitMQ消息服务用户手册(rabbitmq消息id)
- 2024-10-21 索引生命周期管理ILM看完不懂你锤我
- 2024-10-21 Elasticsearch技术问答系列-NO3(elasticsearch curator)
- 2024-10-21 从裸机到700亿参数大模型,这里有份教程,还有现成可用的脚本
- 2024-10-21 「一文搞懂」Nacos健康检查机制(nacos修改健康检查模式)
- 2024-10-21 「ceph-deploy」CentOS7部署Ceph-nautilus 14.2.18版本集群学习
- 2024-10-21 Kibana 最常见的“启动报错”的故障原因及解决方案汇总
- 2024-10-21 二进制部署Kubernetes V1.18.X(etcd集群篇)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)