Jvm参数优化

2023-10-29

背景

假设项目每天100w次登陆请求,一个服务器节点8G内存,如何设置JVM参数?
在这里插入图片描述

1. 系统上线规划容量

- 分析

  1. 100W请求登录峰值在早上,预估峰值每秒100次登录请求
  2. 假设部署3台服务器.每台处理30次请求,假设登录请求处理需要1s,JVM新生代里每秒就要产生30个登陆对象,1s之后请求完毕的这些对象成为垃圾.
  3. 一个登陆请求对象假设20个字段,一个对象估算500字节,30个登陆佔用大约15kb,考虑到RPC和DB操作,网络通信、写库、写缓存一顿操作下来,可以扩大到20-50倍,大约1s产生几百k-1M数据。
  4. 假设2C4G机器部署,分配2G堆内存,新生代则只有几百M,按照1s1M的垃圾产生速度,几百秒就会触发一次MinorGC了
  5. 假设4C8G机器部署,分配4G堆内存,新生代分配2G,如此需要几个小时才会触发一次MinorGC。
    可以粗略的推断出来一个每天100w次请求的登录系统,按照4C8G的3实例集群配置,分配4G堆内存、2G新生代的JVM,可以保障系统的一个正常负载

2. 垃圾回收器选择

吞吐量和响应时间

吞吐量 = CPU在用户应用程序运行的时间 / (CPU在用户应用程序运行的时间 + CPU垃圾回收的时间)
响应时间 = 平均每次的GC的耗时
通常,吞吐优先还是响应优先这个在JVM中是一个两难之选,无法同时兼顾。

垃圾回收器选择

目前主流垃圾回收器CMS或者G1
G1是官方维护和推荐的垃圾回收器
在这里插入图片描述
系统对延迟敏感的推荐CMS
系统大内存,要求高吞吐的,采用G1回收器

3. 规划各个分区的比例大小

  • 指定堆内存的大小,这是系统上线必须要做的,-Xms初始堆大小,-Xmx 最大堆大小,一般指定为系统内存的一半.
  • 指定新生代大小-Xmn,官方推荐为3/8大小,根据业务场景去区分,无状态服务一般给到堆内存的3/4大小,有状态的服务(IM,网关)堆内存的1/3大小
  • 栈内存-Xss,设置单个线程栈的大小,默认值和JDK版本有关,一般默认512-1024kb
    在这里插入图片描述
    如果采用正常的JVM参数配置如下
-Xms3072M 
-Xmx3072M 
-Xss1M 
-XX:MetaspaceSize=256M 
-XX:MaxMetaspaceSize=256M 
-XX:SurvivorRatio=8 

这样设置可能会由于动态对象年龄判断原则导致频繁full gc
压测过程中,短时间(比如20S后)Eden区就满了,此时再运行的时候对象已经无法分配,会触发MinorGC,
假设在这次GC后S1装入100M,马上过20S又会触发一次MinorGC,多出来的100M存活对象+S1区的100M已经无法顺利放入到S2区,此时就会触发JVM的动态年龄机制,将一批100M左右的对象推到老年代保存,持续运行一段时间,系统可能一个小时候内就会触发一次FullGC。
按照默认8:1:1的比例来分配时, survivor区只有 1G的 10%左右,也就是几十到100M.
将JVM参数更改为下面参数

-Xms3072M   
-Xmx3072M   
-Xmn2048M   
-Xss1M   
-XX:MetaspaceSize=256M   
-XX:MaxMetaspaceSize=256M    
-XX:SurvivorRatio=8
  • 年轻代大小2G, eden与survivor的比例1.6g:0.2g
    这样可以防止每次垃圾回收过后,survivor对象太早超过 50% ,
    就可以降低因为对象动态年龄判断原则导致的对象频繁进入老年代的问题,
    在这里插入图片描述

4. 对象年龄对少移动到老年代合适

如果对象这么长时间都没被回收,比如2分钟没有回收,可以认为这些对象是会存活的比较长的对象,从而移动到老年代,而不是继续一直占用survivor区空间。
默认值是15, 意味着对象要经过15次minor GC才会进入老年代
调整参数如下:

‐Xms3072M   
‐Xmx3072M   
‐Xmn2048M   
‐Xss1M   
‐XX:MetaspaceSize=256M   
‐XX:MaxMetaspaceSize=256M   
‐XX:SurvivorRatio=8   
‐XX:MaxTenuringThreshold=5  

5. 对象多大放到老年代

对象直接进入老年代参数-XX:PretenureSizeThreshold

‐Xms3072M   
‐Xmx3072M   
‐Xmn2048M   
‐Xss1M   
‐XX:MetaspaceSize=256M   
‐XX:MaxMetaspaceSize=256M   
‐XX:SurvivorRatio=8   
‐XX:MaxTenuringThreshold=5   
‐XX:PretenureSizeThreshold=1M 

6. 垃圾回收器CMS老年代参数优化

JDK8默认的垃圾回收器是-XX:+UseParallelGC(年轻代)和-XX:+UseParallelOldGC(老年代).
如果内存比较大,建议使用G1

‐Xms3072M   
‐Xmx3072M   
‐Xmn2048M   
‐Xss1M   
‐XX:MetaspaceSize=256M   
‐XX:MaxMetaspaceSize=256M   
‐XX:SurvivorRatio=8    
‐XX:MaxTenuringThreshold=5   
‐XX:PretenureSizeThreshold=1M   
‐XX:+UseParNewGC   
‐XX:+UseConcMarkSweepGC   
‐XX:CMSInitiatingOccupancyFraction=70   
‐XX:+UseCMSInitiatingOccupancyOnly   
‐XX:+AlwaysPreTouch 

参数说明
1.‐Xms3072M ‐Xmx3072M 最小最大堆设置为3g,最大最小设置为一致防止内存抖动
2.‐Xss1M 线程栈1m
3.‐Xmn2048M ‐XX:SurvivorRatio=8 年轻代大小2g,eden与survivor的比例为8:1:1,也就是1.6g:0.2g:0.2g
4.-XX:MaxTenuringThreshold=5 年龄为5进入老年代 5.‐XX:PretenureSizeThreshold=1M 大于1m的大对象直接在老年代生成
6.‐XX:+UseParNewGC ‐XX:+UseConcMarkSweepGC 使用ParNew+cms垃圾回收器组合
7.‐XX:CMSInitiatingOccupancyFraction=70 老年代中对象达到这个比例后触发fullgc
8.‐XX:+UseCMSInitiatinpOccupancyOnly 老年代中对象达到这个比例后触发fullgc,每次
9.‐XX:+AlwaysPreTouch 强制操作系统把内存真正分配给IVM,而不是用时才分配。

7. 配置OOM时的内存dump文件和GC日志

增加了GC日志打印、OOM自动dump等配置内容

  • dump配置
-XX:+HeapDumpOnOutOfMemoryError 
-XX:+HeapDumpOnOutOfMemoryError   
-XX:HeapDumpPath=${LOGDIR}/  
  • GC日志配置
-Xloggc:/log/xxx/gc.log   
-XX:+PrintGCDateStamps   
-XX:+PrintGCDetails 

8. 通用JVM参数模板

  • CMS回收器参数模板
-Xms4g  
-Xmx4g  
-Xmn2g  
-Xss1m  
-XX:SurvivorRatio=8  
-XX:MaxTenuringThreshold=10  
-XX:+UseConcMarkSweepGC  
-XX:CMSInitiatingOccupancyFraction=70  
-XX:+UseCMSInitiatingOccupancyOnly  
-XX:+AlwaysPreTouch  
-XX:+HeapDumpOnOutOfMemoryError  
-verbose:gc  
-XX:+PrintGCDetails  
-XX:+PrintGCDateStamps  
-XX:+PrintGCTimeStamps  
-Xloggc:gc.log 
  • G1回收器参数模板
-Xms8g  
-Xmx8g  
-Xss1m  
-XX:+UseG1GC  
-XX:MaxGCPauseMillis=150  
-XX:InitiatingHeapOccupancyPercent=40  
-XX:+HeapDumpOnOutOfMemoryError  
-verbose:gc  
-XX:+PrintGCDetails  
-XX:+PrintGCDateStamps  
-XX:+PrintGCTimeStamps  
-Xloggc:gc.log

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jvm参数优化 的相关文章

  • 在 Eclipse 中隐藏重复的工具栏项

    我不知道如何 但我的 STS 有重复的工具栏项目 我不知道如何删除它们 这是我复制的工具栏的样子 我想摆脱这些 我试图隐藏工具栏 但这没有帮助 有人知道如何删除重复的吗 自从升级到 Oxygen 以来 我一直遇到同样的问题 我无法可靠地重现
  • Android CursorAdapter、ListView 和后台线程

    我一直在开发的这个应用程序有包含数兆字节数据的数据库可供筛选 许多活动只是列表视图 通过数据库中的各个级别的数据下降 直到到达 文档 即从数据库中提取并显示在手机上的 HTML 我遇到的问题是 其中一些活动需要能够通过捕获击键并重新运行带有
  • APNS(Apple 推送通知服务器)的反馈服务

    我们正在使用Java作为推送通知提供商APNS I我能够将消息发送到APNS但我不知道如何获得该消息的反馈 请帮忙 反馈服务具有类似于用于发送推送通知的接口的二进制接口 您可以通过以下方式访问生产反馈服务feedback push appl
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • 为什么这个动作不抽象? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我很难理解为什么一个类中的一个操作是抽象的 而另一个类中的操作不是 源代码1 编译时出错 https gyazo com cd3c
  • Apache Commons VFS - 无法解析文件

    VFS 方法无法处理此 URI jboss server temp dir local outgoing配置在jboss beans xml这是决心 C Download jboss eap 5 1 1 server default tmp
  • 外部实体更改后索引不更新

    我目前正在开发一个项目 使用 JPA 2 1 保存数据并使用 hibernate search 4 5 0 final 搜索实体 映射类和索引后 搜索工作正常 但是 当我更改值时描述B 类从 someStr 到 anotherStr 数据库
  • 如何修复maven错误JAVA_HOME环境变量未正确定义

    当我在虚拟环境中检查maven的版本时 出现以下错误 The JAVA HOME environment variable is not defined correctly This environment variable is need
  • 生产者程序中的 kafka 网络处理器错误(ArrayIndexOutOfBoundsException:18)

    我有下面的 kafka Producer Api 程序 我对 kafka 本身是新手 下面的代码从 API 之一获取数据并将消息发送到 kafka 主题 package kafka Demo import java util Propert
  • 使用java在网页中进行字符编码

    如何使用java找出网页中的字符编码类型 打开与 URL 的连接 使用URL openConnection http download oracle com javase 6 docs api java net URL html openC
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Java:不使用 Arrays.sort() 对整数数组进行排序

    这是我们 Java 课程的练习之一中的说明 首先 我想说我 做了我的功课 我不仅仅是懒惰地请 Stack Overflow 上的人帮我回答这个问题 在所有其他练习中 这个特定项目一直是我的问题 因为我一直在努力寻找 完美的算法 编写JAVA
  • Hazelcast:连接到远程集群

    我们有一组 Hazelcast 节点 全部运行在一个远程系统 具有许多节点的单个物理系统 上 我们希望从外部客户端连接到该集群 一个 Java 应用程序 它使用如下代码连接到 Hazelcast ClientConfig clientCon
  • 按名称获取 ArrayList

    这是正确的获取方式吗ArrayList
  • 在Java中将日期“2020-05-22T12:51:20.765111Z”解析为Instant [重复]

    这个问题在这里已经有答案了 如何解析 2020 05 22T12 51 20 732111Z Java 中的 Instant I used LocalDateTime parse startTime DateTimeFormatter of
  • Java8 项目上的 SonarQube 给出 jacoco-Exception

    我刚刚下载了最新版本 SonarQube 4 3 然后尝试使用以下命令构建 java 8 项目 mvn clean install mvn sonar sonar 这给了我下面的例外 谷歌搜索 我的印象是这是一个早期的问题 应该已经解决 h
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • 如何在apache POI中读取excel文件的准确单元格内容

    当我读取单元格的内容时 例如如果它是日期格式 它会转换为另一个值 例如 12 31 2099 gt 46052 和 50 00 gt 50 和 50 00 gt 0 5 但我想要的是获取每个单元格的确切字符串值 我的代码是这样的 cell
  • while循环只执行一次

    我很难弄清楚为什么 while 循环实际上不会循环 它运行一次并停止 import java util public class mileskm public static void main String args Scanner inp
  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str

随机推荐