Linux-tomcat性能优化

Tomcat 性能优化常用配置

Tomcat在目前的网络编程中是举足轻重的,由于Tomcat的运行依赖于 JVM,从虚拟机的角度把Tomcat的调整分为外部环境调优 JVM 和 Tomcat 自身调优两部分

 

JVM 组成部分

  • 类加载子系统: 使用Java语言编写.java Source Code文件,通过javac编译成.class Byte Code文件。class loader类加载器将所需所有类加载到内存,必要时将类实例化成实例
  • 运行时数据区: 最消耗内存的空间,需要优化
  • 执行引擎: 包括JIT (JustInTimeCompiler)即时编译器, GC垃圾回收器本地方法接口: 将本地方法栈通过JNI(Java Native Interface)调用Native Method Libraries, 比如:C,C++库等,扩展Java功能,融合不同的编程语言为Java所用

JVM运行时数据区域由下面部分构成:

  • Method Area 方法区(线程共享):所有线程共享的内存空间,存放已加载的类信息(构造方法,接口 定义),常量(final),静态变量(static), 运行时常量池等。但实例变量存放在堆内存中. 从JDK8开始此空 间由永久代改名为元空间
  • heap 堆(线程共享):虚拟机启动时创建,存放创建的所有对象信息。如果对象无法申请到可用内存 将抛出OOM异常.堆是靠GC垃圾回收器管理的,通过-Xmx -Xms 指定最大堆和最小堆空间大小
  • Java stack Java栈(线程私有):每个线程会分配一个栈,存放java中8大基本数据类型,对象引用,实 例的本地变量,方法参数和返回值等,基于FILO()(First In Last Out),每个方法为一个栈帧
  • Program Counter Register PC寄存器(线程私有):就是一个指针,指向方法区中的方法字节码,每 一个线程用于记录当前线程正在执行的字节码指令地址。由执行引擎读取下一条指令.因为线程需要 切换,当一个线程被切换回来需要执行的时候,知道执行到哪里了
  • Native Method stack 本地方法栈(线程私有):为本地方法执行构建的内存空间,存放本地方法 执行时的局部变量、操作数等。

 JVM优化

垃圾回收基本算法

标记-清除 Mark-Sweep

分垃圾标记阶段和内存释放阶段。标记阶段,找到所有可访问对象打个标记。清理阶段,遍历整个堆, 对未标记对象(即不再使用的对象)清理。

 

标记-压缩 (压实)Mark-Compact

标记-压缩算法好处是整理后内存空间连续分配,有大段的连续内存可分配,没有内存碎片。 缺点是内存整理过程有消耗,效率相对低下

 

复制 Copying

先将可用内存分为大小相同两块区域A和B,每次只用其中一块,比如A。当A用完后,则将A中存活的对 象复制到B。复制到B的时候连续的使用内存,最后将A一次性清除干净。

缺点是比较浪费内存,只能使用原来一半内存,因为内存对半划分了,复制过程毕竟也是有代价。

好处是没有碎片,复制过程中保证对象使用连续空间

 

多种算法总结

没有最好的算法,在不同场景选择最合适的算法

效率: 标记清除算法>复制算法> 标记压缩算法 
内存整齐度: 复制算法
=标记压缩算法> 标记清除算法
内存利用率: 标记压缩算法
=标记清除算法>复制算法

 

 分代堆内存GC策略

 

将heap内存空间分为三个不同类别: 年轻代、老年代、持久代

复制代码
Heap堆内存分为
  年轻代Young:Young Generation
  伊甸园区eden: 只有一个,刚刚创建的对象
  幸存(存活)区Servivor Space:有2个幸存区,一个是from区,一个是to区。大小相等、地位相同、可互换。
    from 指的是本次复制数据的源区
    to 指的是本次复制数据的目标区
老年代Tenured:Old Generation, 长时间存活的对象
永久代:JDK1.7之前使用, 即Method Area方法区,保存JVM自身的类和方法,存储JAVA运行时的环境信息,JDK1.8后 改名为 MetaSpace,此空间不存在垃圾回收,关闭JVM会释放此区域内存,此空间物理上不属于heap内存,但逻辑上存在于heap内存
  永久代必须指定大小限制,字符串常量JDK1.7存放在永久代,1.8后存放在heap中
  MetaSpace 可以设置,也可不设置,无上限
复制代码

年轻代回收 Minor GC

复制代码
. 起始时,所有新建对象(特大对象直接进入老年代)都出生在eden,当eden满了,启动GC。这个称为Young GC 或者 Minor GC。
. 先标记eden存活对象,然后将存活对象复制到s0(假设本次是s0,也可以是s1,它们可以调换),eden剩余所有空间都清空。GC完成。
. 继续新建对象,当eden再次满了,启动GC。
. 先同时标记eden和s0中存活对象,然后将存活对象复制到s1。将eden和s0清空,此次GC完成
. 继续新建对象,当eden满了,启动GC。
. 先标记eden和s1中存活对象,然后将存活对象复制到s0。将eden和s1清空,此次GC完成以后就重复上面的步骤。
通常场景下,大多数对象都不会存活很久,而且创建活动非常多,新生代就需要频繁垃圾回收。
但是,如果一个对象一直存活,它最后就在from、to来回复制,如果from区中对象复制次数达到阈值
(默认15次,CMS为6次,可通过java的选项 -XX:MaxTenuringThreshold=N 指定),就直接复制到老年
代。
复制代码

老年代回收 Major GC

进入老年代的数据较少,所以老年代区被占满的速度较慢,所以垃圾回收也不频繁。
如果老年代也满了,会触发老年代GC,称为Old GC或者 Major GC。
由于老年代对象一般来说存活次数较长,所以较常采用标记-压缩算法。
当老年代满时,会触发 Full GC,即对所有""的内存进行垃圾回收
Minor GC比较频繁,Major GC较少。但一般Major GC时,由于老年代对象也可以引用新生代对象,所以先进行一次Minor GC,然后在Major GC会提高效率。可以认为回收老年代的时候完成了一次FullGC。
所以可以认为 MajorGC = FullGC
年轻代:
  存活时长低
  适合复制算法
老年代:
  区域大,存活时长高
  适合标记清除和标记压缩算法

 

Tomcat的JVM参数设置

默认不指定,-Xmx大约使用了1/4的内存,当前本机内存指定约为1G。 在bin/catalina.sh中增加一行

......
# OS specific support. $var _must_ be set to either true or false.
#添加下面一行
JAVA_OPTS="-server -Xms128m -Xmx512m -XX:NewSize=48m -XX:MaxNewSize=200m"
                                                            
cygwin=false
darwin=false
........
-server:VM运行在server模式,为在服务器端最大化程序运行速度而优化
-client:VM运行在Client模式,为客户端环境减少启动时间而优化

 

指定垃圾回收设置

复制代码
#将参数加入到bin/catalina.sh中,重启观察Tomcat status。老年代已经使用CMS
[root@tomcat ~]#vim /usr/local/tomcat/bin/catalina.sh
......
# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="-server -Xmx512m -Xms128m -XX:NewSize=48m -XX:MaxNewSize=200m -
XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -
XX:CMSFullGCsBeforeCompaction=5"                                                
                                                         
cygwin=false
darwin=false
os400=false
.......
复制代码

 

内存空间优化

JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小
-XX:MaxNewSize=:新生代空间最大值

 生产案例:

复制代码
[root@centos7 ~]#vim /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"
#一台tomcat服务器并发连接数不高,生产建议分配物理内存通常4G到8G较多,如果需要更多连接,一般会利用
虚拟化技术实现多台tomcat
复制代码

tomcat优化 

线程池调整

[root@centos7 ~]#vim /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

 

posted @   goodbay说拜拜  阅读(413)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示