沉舟侧畔千帆进,病树前头万木春。这篇文章主要讲述Tomcat的优化及OOM问题相关的知识,希望能为你提供帮助。
1.Tomcat优化在目前流行的互联网架构中,Tomcat在网络编程中有着举足轻重的地位,Tomcat的调优可以从两个维度去考虑:一是外部环境调优;二是Tomcat的运行依赖的JVM和Tomcat 自身调优。
1.1Tomcat调优--外部环境维度
- 根据业务模型,规划最佳的架构,并优化。比如:Tomcat集群的引入、前端反向代理的采用、动静分离等。
- Tomcat 只是作为java程序运行空间,JAVA程序自身的优化也是提高Tomcat性能的重要因素。
- 服务器硬件的优选,高带宽内存、高缓存CPU、高读写的磁盘(固态硬盘),解决性能短板。
- 利用缓存和压缩技术:静态页面可采用缓存技术,提高响应速度,将图片、css、js文件都进行了缓存,有效的减少了后端tomcat的重复任务。
- 提高网络性能:选用更大带宽和速率的网络技术,比如:40G、80G、100G等,提高服务器之间数据交互,也提高客户端的访问性能。
- 虚拟化和容器化技术:鉴于Tomcat自身的因素,一台 tomcat 服务器并发连接数无法堆砌得很高,按照惯例一般生产建议8G左右一个虚拟机或者容器跑Tomcat比较被推荐,如果一台服务器物理内存很高,可以通过虚拟化技术或者容器技术实现多台tomcat集群,来完成前端的大并发用户请求。
1.2Tomcat调优--JVM运行环境等内部配置维度
1.2.1内存空间优化Tomcat是运行在JVM上的,对JVM的调优也尤为重要。
JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小
-XX:MaxNewSize=:新生代空间最大值
# tomcat服务器并发连接数不高,生产建议分配物理内存通常4G到8G较多
[root@CentOS84 ~]#cat/usr/local/tomcat/bin/catalina.sh
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -
XX:CMSInitiatingOccupancyFraction=65 -XX:+AggressiveOpts -XX:+UseBiasedLocking -
XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -
XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -
XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -
XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -
XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
1.2.2线程池调整
[root@CentOS84 ~]#cat /usr/local/tomcat/conf/server.xml
......
< Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"
redirectPort="8443" />
......
常用参数选项:
- connectionTimeout :连接超时时长,单位ms
- maxThreads:最大线程数,默认200
- minSpareThreads:最小空闲线程数
- maxSpareThreads:最大空闲线程数
- acceptCount:当启动线程满了之后,等待队列的最大长度,默认100
- URIEncoding:URI 地址编码格式,建议使用 UTF-8
- enableLookups:是否启用客户端主机名的DNS反向解析,缺省禁用,建议禁用,就使用客户端IP就行
- compression:是否启用传输压缩机制,建议 "on",CPU和流量的平衡
- compressionMinSize:启用压缩传输的数据流最小值,单位是字节
- compressableMimeType:定义启用压缩功能的MIME类型text/html, text/xml, text/css,text/javascript
1.2.3Tomcat连接器Connector 调优打开Tomcat的server.xml,配置Connector的相关项
- enableLookups == false:关闭DNS解析,减少性能损耗【这个优化很重要的,一般都要关闭掉】
- minProcessors:服务器启动时创建的最少线程数
- maxProcessors:最大可以创建的线程数
- acceprCount=1000:线程池中的线程都被占用,允许放到队列中的请求数
- maxThreads = 3000;最大线程数
- minSpareThreads = 20; 最小空线程数,这里是一直会运行的线程
1.2.4Tomcat的运行模式的优选Tomcat 支持多种运行模式,依据业务类型选择合适的运行模式:
- BIO,在tomcat8以下,默认使用BIO模式,对于每一个请求都要创建一个线程来进行处理,不适合高并发。
- NIO,tomcat8以上的版本,默认使用NIO。
- APR,全称 Apache Portable Runtime,是Tomcat生产环境运行的默认方式,如果操作系统未安装 APR 或者 APR 路径未指到 Tomcat 默认可识别的路径,则 APR 模式无法启动,自动切换启动 NIO 模式。所以必须要安装 APR 和 Native,直接启动就支持 APR,APR是从操作系统级别解决异步 IO 问题,APR 的本质就是使用 JNI 技术调用操作系统底层的 IO 接口,所以需要提前安装所需要的依赖提升 Tomcat 对静态文件的处理性能,当然也可以采用动静分离。但是如果使用的是nginx 搭配 Tomcat,则需要禁用AJP连接器。
2.什么场景下会出现OOM?Java程序出现OOM如何解决?2.1OOM定义及原因
OOM(内存溢出Out Of Memory,简称OOM)是java.lang.OutOfMemoryError问题,出现在程序需要的内存空间,系统无法提供满足要求的连续可用内存空间,所以会导致出现这个问题。具体表现为应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件,而由系统配置、数据流、用户代码等原因而导致的内存溢出错误,即使用户重新执行任务依然无法避免。
2.2几种主要的OOM
【Tomcat的优化及OOM问题】1、HeapSize OOM(堆空间内存溢出)
关键字:java.lang.OutOfMemoryError:java heap space
这是堆空间溢出。老年代区域剩余的内存,已经无法满足将要晋升到老年代区域的对象大小,会报此错。
2、PermGen OOM(永久代内存溢出)
关键字:java.lang.OutOfMemoryError:PermGen space
永久代(PermGen space)是JVM实现方法区的地方,因此该异常主要设计到方法区和方法区中的常量池。永久代存放的东西有class和一些常量。perm是放永久区的。如果一个系统定义了太多的类型,那永久区可能会溢出。jdk1.8中,被称为元数据区。
3、DirectBuffer OOM(直接内存内存溢出)
关键字:OutOfMemoryError: Direct buffer memory
Java中普通I/O用输入/输出流方式实现,输入流InputStream(终端—> 直接内存-> JVM),输出流(JVM-> 直接内存-> 终端),这一过程中有kenel与JVM之间的拷贝(很多次),为了使用直接内存,Java是有一块区域叫DirectBuffer,不是JavaHeap而是cHeap的一部分。
2.3解决OOM
内存溢出的解决方案:
第一步:检查 JVM 启动参数是否已经优化,是否可以增加内存等。 (-Xms , -Xmx 参数一定不要忘记加。 )
第二步:检查错误日志,查看 “ OutOfMemory ”错误前是否有系统类的异常或错误导致的,尽量能初步定位下OOM原因。
第三步:对代码进行检查和分析,找出可能发生内存溢出的位置。可借助Jprofiler等工具去定位OOM的问题原因和代码行,再去调整内存分配和代码优化,这样有的放矢地去解决掉导致OOM的问题。
重点排查以下几点:
1、检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
2、检查代码中是否有死循环或递归调用。
3、检查是否有大循环重复产生新对象实体。
4、检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
5、 检查 List 、 MAP 等集合对象是否有使用完后,未清除的问题。 List 、 MAP 等集合对象会始终存有对对象的引用,使得这些对象不能被 GC 回收。
第四步,使用内存查看工具动态查看电脑内存使用情况,跟踪内存消耗的动态信息。
推荐阅读
- windows下创建本地git仓库
- 如何用C/C++实现去除字符串头和尾指定的字符
- 因为实现不了Promise.all,一场面试凉凉了
- RocketMQ集群部署
- 有奖调研 | 即时消息服务的产品需求规划就交给你了!
- 面试官问你 JVM,你知道加分项在哪吗()
- 一行Python代码,给PDF文件添加水印,快速而且免费~python-office自动化办公,YYDS
- Sublime快捷键设置
- C#/VB.NET 合并PDF页面