Tomcat调优

devtools/2024/9/20 7:11:30/ 标签: tomcat, java

文章目录

  • 一、JVM组成
    • JVM组成
    • 堆和栈的拓展
    • 垃圾回收
      • 垃圾确定方法
      • 垃圾回收基本算法
    • 分代堆内存垃圾回收策略
      • 堆内存分代
  • 二、参数调整
    • java 内存调整相关参数
    • Tomcat的JVM的参数设置


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

一、JVM组成

JVM组成

在这里插入图片描述

  • 类加载子系统(class loader subsystem): 使用Java语言编写.java Source Code文件,通过javac编译成.class Byte Code文件。class loader类加载器将所需所有类加载到内存,必要时将类实例化成实例

  • 运行时数据区(runtime data areas): java程序在运行时所占用的内存时间,最消耗内存的空间,需要优化。

  • 执行引擎(execution engine): 包括JIT (JustInTimeCompiler)即时编译器, GC垃圾回收器。

  • 本地方法接口(native method interface): 将本地方法栈通过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 (线程私有): 本地方法栈为本地方法执行构建的内存空间,存放本地方法执行时的局部变量、操作数等。

在这里插入图片描述

堆和栈的拓展

CPU内部有个模块叫ALU专门用来做逻辑运算,但进行复杂运算时,需要存储临时结果,那这时候就需要有一块空间存放临时结果这个空间就叫寄存器有了寄存器cpu 就可以分步计算,需要临时结果时可以从临时寄存器中取回数据。但CPU是用于运算的,并不可能有很多寄存器,所以内存中划出一片专门的空间用于存储 cpu的临时数据,既然是专用的那么就得有个名字就叫栈stack,除了栈还划分了一块区域叫堆。

堆(Heap):

  • 动态内存分配:堆用于存储动态分配的内存。程序可以在运行时从堆中动态分配内存,这使得程序能够根据需要动态创建、修改和释放内存空间。
  • 存储复杂数据结构:堆适合存储较大或者不确定大小的数据结构,如链表、树等。在堆上分配的内存区域对于数据的存储和访问比较灵活。
  • 手动管理内存:在堆上分配内存需要程序员手动管理内存的分配和释放,避免内存泄漏或者访问越界的问题。

栈(Stack):

  • 函数调用和局部变量存储:栈用于存储函数调用和局部变量。每次函数调用时,参数、返回地址和局部变量等数据会被压入栈中,函数执行完后再弹出。
  • 自动管理内存:栈上的内存由系统自动管理,无需程序员显式地分配和释放。栈上的数据的生命周期与函数调用的作用域相关,当函数退出时,栈上的数据会被自动释放。
  • 快速访问:栈的数据结构是先进后出(FILO),只能从栈顶进行操作,访问速度较快。

堆(Heap):堆就像是您桌子上的堆积木一样,您可以随意地在桌子上放置、移动和删除堆积木。每块堆积木可能拥有不同的大小和形状,您可以根据需要动态地分配和释放这些堆积木。堆中的内存空间通常是动态分配的,需要程序员手动管理分配和释放。在堆上分配的内存可以根据需要动态增加或减少,但在使用过程中需要显式地进行内存管理。

栈(Stack):栈就像是您手中叠盘子的过程,您一层一层地往上叠加盘子。每叠一层盘子,您只能在最上面的一层添加或移除盘子。栈具有先进后出(FILO)的特性,最后放入的盘子会最先被拿走。这意味着栈中只能从顶部添加或删除数据,不能随意访问栈中间的数据。栈是一种固定大小的内存结构,由系统自动管理,存储函数调用、局部变量等数据。

垃圾回收

安卓程序需要运行在JVM上,而安卓平台使用了Google自研的Java虚拟机— —Dalvid,适合于内存、处理器能力有限系统。

在堆内存中如果创建的对象不再使用,仍占用着内存,此时即为垃圾。需要即使进行垃圾回收,从而释放内存空间给其它对象使用。不同的开发语言都有垃圾回收问题,C,C++需要程序员人为回收,造成开发难度大,容易出错等问题,但执行效率高,而JAVA和Python中不需要程序员进行人为的回收垃圾,而由JVM或相关程序自动回收垃圾,减轻程序员的开发难度,但可能会造成执行效率低下。
堆内存里面经常创建、销毁对象,内存也是经常被使用、被释放。如果不妥善处理,一个使用频繁的进程,可能会出现虽然有足够的内存容量,但是无法分配出可用内存空间,因为没有连续成片的内存了,内存全是碎片化的空间。所以需要有合适的垃圾回收机制,确保正常释放不再使用的内存空间,还需要保证内存空间尽可能的保持一定的连续。

那什么是java程序里的垃圾?
长时间没有被使用的进程和线程。
对于垃圾回收,需要解决三个问题。

  • 哪些垃圾需要回收。
  • 怎么回收垃圾。
  • 什么时候回收垃圾。

垃圾确定方法

引用计数: 每一个堆内对象上都与一个私有引用计数器,记录着被引用的次数,引用计数清零,该对象所占用堆内存就可以被回收。循环引用的对象都无法将引用计数归零,就无法清除。Python中使用此种方式。
简单来说就是有个本子,随时记录有没有人在使用。但缺陷在于如果AB资源相互引用,即使是垃圾,但也不会被清除。
根搜索(可达)算法:
在这里插入图片描述
简单来说,根搜索算法的步骤如下:

  • 选择一个起始节点作为根节点。
  • 访问这个根节点,并标记为已访问。
  • 遍历根节点的邻接节点(通过边与根节点相连的节点)。
  • 依次遍历邻接节点的邻接节点,持续深入图结构。
  • 在这个过程中,确保避免重复访问已经标记过的节点。
  • 当无法再找到未访问的邻接节点时,表示到达尽头,搜索结束。

遍历到的进程不是垃圾进程,遍历不到的进程就是垃圾进程。

垃圾回收基本算法

标记-清除 Mark-Sweep
过程分垃圾标记阶段和内存释放阶段。标记阶段,找到所有可访问对象打个标记。清理阶段,遍历整个堆,对未标记对象(即不再使用的对象)逐一进行清理。
在这里插入图片描述
标记-清除最大的问题会造成内存碎片 (即不是连续的内存空间),但是不浪费空间,效率较高。如果对象较多,逐一删除效率也会影响。

标记压缩 (压实)Mark-Compact
分垃圾标记阶段和内存整理阶段。标记阶段,找到所有可访问对象打个标记。内存清理阶段时,整理时将对象向内存一端移动,整理后存活对象连续的集中在内存一端。
在这里插入图片描述
标记-压缩算法好处是整理后内存空间连续分配,有大段的连续内存可分配,没有内存碎片。缺点是内存整理过程有消耗,效率相对低下

复制Copying
先将可用内存分为大小相同两块区域A和B,每次只用其中一块,比如A。当A用完后,则将A中存活的对象复制到B。复制到B的时候连续的使用内存,最后将A一次性清除干净。缺点是比较浪费内存,只能使用原来一半内存,因为内存对半划分了,复制过程毕竟也是有代价。好处是没有碎片,复制过程中保证对象使用连续空间,且一次性清除所有垃圾,所以效率很高。
在这里插入图片描述
算法总结
我们需要在不同的场景下选择最合适的算法。

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

STW
对于大多数垃圾回收算法而言,GC(Garbage Collection)线程工作时,停止所有工作的线程,称为Stop The World。GC 完成时,恢复其他工作线程运行。这也是JVM运行中最头疼的问题。

分代堆内存垃圾回收策略

堆内存分代

上述垃圾回收算法都有优缺点,能不能对不同数据进行区分管理,不同分区对数据实施不同回收策略,分而治之将heap内存空间分为三个不同类别: 年轻代、老年代、持久代
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Heap堆内存分为

  • 年轻代Young:Young Generation
    • 伊甸园区eden: 只有一个,刚刚创建的对象。
    • 幸存(存活)区Servivor Space:有2个幸存区,一个是from区,一个是to区。大小相等、地位相同、可互换。
      • from 指的是本次复制数据的源区
      • to 指的是本次复制数据的目标区
  • 老年代Tenured:Old Generation, 长时间存活的对象。

默认空间大小比例:
在这里插入图片描述
注意:在tomcat 状态页可以看到以下的内存分代 持久代是 元空间 metaspace

[root@localhost mnt]#vim /usr/local/tomcat/conf/tomcat-users.xml
#只可以本地登录
<tomcat-users>
.......
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>

需要配置一下。

年轻代回收Minor GC

  1. 起始时,所有新建对象(特大对象直接进入老年代)都出生在eden,当eden满了,启动GC。这个称为Young GC 或者Minor GC。

  2. 标记eden存活对象,然后将存活对象复制到s0(假设本次是s0,也可以是s1,它们可以调换),eden剩余所有空间都清空。GC完成

  3. 继续新建对象,当eden再次满了,启动GC

  4. 先同时标记eden和s0中存活对象,然后将存活对象复制到s1。将eden和s0清空,此次GC完成

  5. 继续新建对象,当eden满了,启动GC

  6. 先标记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会提高效率。可以认为回收老年代的时候完成了一次Full GC。所以可以认为 MajorGC = FullGC。

在这里插入图片描述

二、参数调整

java__150">java 内存调整相关参数

 Java 命令行参考文档: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

在这里插入图片描述
这里调整的参数,是调整jvm虚拟机的启动内存等参数,还有垃圾回收参数。

选项分类

  • -选项名称 此为标准选项,所有HotSpot都支持
  • -X选项名称 为稳定的非标准选项
  • -XX:选项名称 非标准的不稳定选项,下一个版本可能会取消
参数说明举例
-Xms设置应用程序初始使用的堆内存大小(年轻代+老年代)-Xms2g
-Xmx设置应用程序能获得的最大堆内存早期JVM不建议超过32G,内存管理效率下降-Xms4g
-XX:NewSize设置初始新生代大小-XX:NewSize=128m
-XX:MaxNewSize设置最大新生代内存空间-XX:MaxNewSize=256m
-Xmnsize同时设置-XX:NewSize 和 -XX:MaxNewSize,代-Xmn1g
-XX:NewRatio以比例方式设置新生代和老年代-XX:NewRatio=2
new/old=1/2
-XX:SurvivorRatio以比例方式设置eden和survivor(S0或S1)-XX:SurvivorRatio=6
eden/survivor=6/1
new/survivor=8/1
-Xss设置每个线程私有的栈空间大小,依据具体线程-Xss256k

Tomcat的JVM的参数设置

默认不指定,-Xmx大约使用了1/4的内存,当前本机内存指定约为1G。

在bin/catalina.sh中增加一行

118# OS specific support. $var _must_ be set to either true or false.  
#添加下面一行    
JAVA_OPTS="-server -Xms128m -Xmx512m -XX:NewSize=100m -XX:MaxNewSize=200m"JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= "
-server:服务器模式
-Xms:堆内存初始化大小
-Xmx:堆内存空间上限
-XX:NewSize=:新生代空间初始化大小 
-XX:MaxNewSize=:新生代空间最大值                       

Tomcat默认安装下的缺省配置并不适合生产环境,它可能会频繁出现假死现象需要重启,只有通过不断压测优化才能让它最高效率稳定的运行。优化主要包括三方面,分别为操作系统优化(内核参数优化),Tomcat配置文件参数优化,Java虚拟机(JVM)调优。
关于 Tomcat 主配置文件 server.xml 里面很多默认的配置项,但并不能满足业务需求,常用的优化相关参数如下:
【maxThreads】Tomcat 使用线程来处理接收的每个请求,这个值表示 Tomcat 可创建的最大的线程数,默认值是 200。

【minSpareThreads】最小空闲线程数,Tomcat 启动时的初始化的线程数,表示即使没有人使用也开这么多空线程等待,默认值是 10

【maxSpareThreads】最大备用线程数,一旦创建的线程超过这个值,Tomcat 就会关闭不再需要的 socket 线程。默认值是-1(无限制)。一般不需要指定

【URIEncoding】指定 Tomcat 容器的 URL 编码格式,语言编码格式这块倒不如其它 Web服务器软件配置方便,需要分别指定utf-8

【connnectionTimeout】网络连接超时,单位:毫秒,设置为 0 表示永不超时,这样设置有隐患的。通常默认 20000 毫秒(20秒)就可以

【enableLookups】是否反查域名,以返回远程主机的主机名,取值为:true 或 false,如果设置为 false,则直接返回 IP 地址,为了提高处理能力,应设置为 false。

【disableUploadTimeout】上传时是否使用超时机制。应设置为 true。

【connectionUploadTimeout】上传超时时间,毕竟文件上传可能需要消耗更多的时间,这个根据你自己的业务需要自己调,以使 Servlet 有较长的时间来完成它的执行,需要与上一个参数一起配合使用才会生效

【acceptCount】指定当所有可以使用的处理请求的线程数都被使用时,可传入连接请求的最大队列长度,超过这个数的请求将不予处理,默认为 100 个。

【compression】是否对响应的数据进行 GZIP 压缩,off:表示禁止压缩;on:表示允许压缩(文本将被压缩)、force:表示所有情况下都进行压缩,默认值为 off,压缩数后可以有效的减少页面的大小,一般可以减小 1/3 左右,节省带宽。

【compressionMinSize】表示压缩响应的最小值,只有当响应报文大小大于这个值的时候才会对报文进行压缩,如果开启了压缩功能,默认值就是 2048

【compressableMimeType】压缩类型,指定对哪些类型的文件进行数据压缩。

【noCompressionUserAgents=“gozilla, traviata”】对于以下的浏览器,不启用压缩。


http://www.ppmy.cn/devtools/56232.html

相关文章

CSS 核心知识点 - grid

思维导图 参考网址: https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_grid_layout 一、什么是 grid&#xff1f; CSS Grid布局是在CSS3规范中引入的一种新的布局方式&#xff0c;旨在解决传统布局方法&#xff08;如浮动、定位、表格布局&#xff09;存在的许多问题。C…

CAN和CANFD数据写入.asc文件的dll

因为工作需要&#xff0c;需要做一些硬件不是CANoe的上位机&#xff08;比如说周立功CAN,NI-CAN&#xff09;&#xff0c;上位机需要有记录数据的功能&#xff0c;所以用Qt制作了一个记录数据的dll&#xff0c;方便重复使用&#xff08;因为有的客户指定了编程软件&#xff0c;…

SmartEDA革新来袭:融合Multisim与Proteus精髓,引领电子设计新纪元!

在电子设计领域&#xff0c;每一次技术的革新都如同春风化雨&#xff0c;滋润着设计师们的心田。今天&#xff0c;我们迎来了一个划时代的电子设计自动化&#xff08;EDA&#xff09;工具——SmartEDA&#xff0c;它不仅融合了业界知名的Multisim和Proteus的精华&#xff0c;更…

在 Java 中的使用Selenium 测试框架

Selenium 测试框架&#xff1a;在 Java 中的使用 Selenium 测试框架就是这样一个强大的工具&#xff0c;它为 Web 应用的自动化测试提供了全面且高效的解决方案。 一、Selenium 简介 Selenium 是一个开源的自动化测试工具集&#xff0c;专门用于测试 Web 应用程序。它支持多…

nuxt实现vuex持久化

前言&#xff1a; 此处不借助插件实现 store 本地持久化 所有状态持久化 使用 vuex 里面的 replaceState 方法还原 store 的根状态 API 参考 | Vuex 创建 store-cache.js 文件 在 plugins 目录下创建 store-cache.js 文件&#xff1b; store-cache.js export default (ctx) &g…

shell编程实战

1.1 shell脚本编程的步骤 需求分析&#xff1a;确定功能 命令测试&#xff1a;确定脚本需要的关键命令 编辑脚本 测试脚本 1.2 操作 1.2.1 实验一 1.需求描述 (1)统计网络中的服务器的mac 注&#xff1a;ARP&#xff0c;地址解析协议 注&#xff1a; (2)检查哪些主机开…

Ubuntu开机后图像化界面消失只有命令行界面

ubuntu重新安装cpp库时突然黑屏&#xff0c;打开之后&#xff0c;只能手动输入用户名和密码才能登陆&#xff0c;当时最坏的结果就是重新安装系统&#xff0c;但是还是得抢救一下&#xff0c;万幸的是抢救成功了&#xff01;&#xff01;&#xff01; 于是来到第一个博客 参考…

收银系统源码-千呼新零售【分销商城】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

【cf】Edu Codeforces Round 167(Div.2)题解 A - E

文章目录 A. Catch the CoinB. Substring and Subsequence&#xff08;贪心&#xff09;C. Two Movies&#xff08;贪心&#xff09;D. Smithing Skill&#xff08;贪心双指针&#xff09;E. Distance to Different&#xff08;dp&#xff09; A. Catch the Coin y 小于 -1 就…

Talking Web

1. curl 1.1 http curl http://127.0.0.1:80 向目标主机端口发送http请求 1.2 httphead curl -H “Host: 18ed3df584cd48328b5839443aa7b42b” http://127.0.0.1:80 1.3 httppath curl http://127.0.0.1:80/853c64cd218f80d0a59665666fb2ab80 1.4 URL编码路径 &#xff0…

光学相机市场格局:中国光学相机市场评估及未来发展趋势研究报告

欢迎关注GZH《光场视觉》 光学相机行业定义 光学相机是一种利用光学镜头和感光材料&#xff08;如胶片&#xff09;或数字传感器来捕捉图像的装置。光学相机&#xff0c;也常被称作传统相机或胶片相机&#xff0c;其工作原理基于光的折射和聚焦。当光线通过相机的镜头进入时&…

从我邮毕业啦!!!

引言 时间过的好快&#xff0c;转眼间就要从北邮毕业了&#xff0c;距离上一次月度总结又过去了两个月&#xff0c;故作本次总结。 PS: https://github.com/WeiXiao-Hyy/blog整理了后端开发的知识网络&#xff0c;欢迎Star&#xff01; 毕业&#x1f393; 6月1号完成了自己的…

# Kafka_深入探秘者(1):初识 kafka

Kafka_深入探秘者&#xff08;1&#xff09;&#xff1a;初识 kafka 一、kafka 特性 1、Kafka &#xff1a;最初是由 Linkedln 公司采用 Scala 语言开发的一个多分区、多副本并且基于 ZooKeeper 协调的分布式消息系统&#xff0c;现在已经捐献给了 Apache 基金会。目前 Kafka…

【websocket】websocket网课视频记录

仅个人方便回顾。 【WebSocket入门与案例实战-哔哩哔哩】 https://b23.tv/2p1f9t2 课程对应代码仓库: https://gitee.com/duoli-java/websocket-demo.git

[图解]企业应用架构模式2024新译本讲解18-活动记录2

1 00:00:00,940 --> 00:00:04,890 接下来&#xff0c;就是要把这个列表输出到控制台 2 00:00:06,490 --> 00:00:12,280 这里面有3个 3 00:00:15,420 --> 00:00:17,480 Id有了&#xff0c;姓 4 00:00:18,600 --> 00:00:28,500 一个一个取&#xff0c;ID&#xff…

Python 实现Excel转TXT,或TXT文本导入Excel

Excel是一种具有强大的数据处理和图表制作功能的电子表格文件&#xff0c;而TXT则是一种简单通用、易于编辑的纯文本文件。将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存&#xff0c;方便其他程序读取和处理。而将TXT转换为Excel则可以将文本文件中的数据导入…

不是KVM不支持精简置备的磁盘,而是VMM

正文共&#xff1a;999 字 11 图&#xff0c;预估阅读时间&#xff1a;1 分钟 书接上文&#xff08;不会吧&#xff01;KVM竟然不支持磁盘的精简置备&#xff01;&#xff1f;&#xff09;&#xff0c;我们已经掌握了通过“虚拟系统管理器VMM”创建虚拟机的基本方法&#xff0c…

Kafka Stream 流处理设计概述

Kafka Stream 流处理设计概述 Kafka 流处理是指使用 Kafka 及其生态系统中的组件来处理实时数据流。Kafka Streams 是 Kafka 官方 提供的流处理库,它简化了构建流处理应用程序的过程,并与 Kafka 无缝集成。以下是 Kafka 流处理的设 计原理和相关概念。 1. Kafka 流处理基本…

基于matlab的不同边缘检测算子的边缘检测

1 原理 1.1 边缘检测概述 边缘检测是图像处理和计算机视觉中的基本问题&#xff0c;其目的在于标识数字图像中亮度变化明显的点。这些变化通常反映了图像属性的重要事件和变化&#xff0c;如深度不连续、表面方向不连续、物质属性变化和场景照明变化等。边缘检测在特征提取中…

计算机毕业设计Python+Spark知识图谱微博预警系统 微博推荐系统 微博可视化 微博数据分析 微博大数据 微博爬虫 微博预测系统 大数据毕业设计

课题名称 基于Bert模型对微博的言论情感分析设计与实现 课题来源 课题类型 BY 指导教师 学生姓名 专 业 计算机科学与技术 学 号 开题报告内容&#xff1a;&#xff08;调研资料的准备&#xff0c;设计/论文的目的、要求、思路与预期成果&#xff1b;…