当前位置: 首页 > news >正文

怎么建设一个音乐网站长沙做网站微联讯点不错

怎么建设一个音乐网站,长沙做网站微联讯点不错,公司网站建设多少费用济南兴田德润评价,北京企业建设网站前言 本文将通过一个真实的生产环境案例#xff0c;详细展示如何系统性地排查和解决JVM垃圾收集问题。这个案例涵盖了从问题发现、分析诊断到最终解决的完整过程#xff0c;对于理解JVM调优实战具有重要的参考价值。 系统背景 我们的服务是一个高并发的微服务应用#xf…前言 本文将通过一个真实的生产环境案例详细展示如何系统性地排查和解决JVM垃圾收集问题。这个案例涵盖了从问题发现、分析诊断到最终解决的完整过程对于理解JVM调优实战具有重要的参考价值。 系统背景 我们的服务是一个高并发的微服务应用技术栈如下 应用框架Spring Boot指标采集Micrometer监控系统Datadog 说明Micrometer 作为应用监控的门面库支持多种监控系统包括AppOptics、Atlas、Datadog、Dynatrace、Elastic、Ganglia、Graphite、Humio、Influx、Instana、JMX、KairosDB、New Relic、Prometheus、SignalFx、Stackdriver、StatsD、Wavefront 等。 详细信息请参考 https://micrometer.io/docs 问题现象 问题描述 在日常监控中我们发现一个服务节点出现了严重的GC性能问题 最大GC暂停时间经常超过400ms峰值暂停时间达到546ms发生时间02月04日 09:20:00 GC暂停时间监控图 业务影响 这种GC暂停时间严重影响了业务运行 服务超时服务调用超时时间为1秒GC暂停过长导致超时风险性能要求 最大GC暂停时间 200ms平均暂停时间 100ms 业务冲击对客户的交易策略产生了严重影响亟需解决 问题排查过程 第一步系统资源使用分析 CPU负载分析 首先检查CPU使用情况监控数据如下 CPU负载监控图 观察结果 系统负载4.92CPU使用率约7% 重要提示这个监控图中实际隐含了重要线索CPU核心数与GC线程数的不匹配但当时并未察觉异常。 GC 内存使用情况 然后我们排查了这段时间的内存使用情况 从图中可以看到大约 09:25 左右 old_gen 使用量大幅下跌确实是发生了 FullGC。 但 09:20 前后老年代空间的使用量在缓慢上升并没有下降也就是说引发最大暂停时间的这个点并没有发生 FullGC。 当然这些是事后复盘分析得出的结论。当时对监控所反馈的信息并不是特别信任怀疑就是触发了 FullGC 导致的长时间 GC 暂停。 为什么有怀疑呢因为 Datadog 这个监控系统默认 10s 上报一次数据。有可能在这 10s 内发生些什么事情但是被漏报了当然这是不可能的如果上报失败会在日志系统中打印相关的错误。 再分析上面这个图可以看到老年代对应的内存池是 “ps_old_gen”通过前面的学习我们知道ps 代表的是 ParallelGC 垃圾收集器。 第三步JVM配置分析 启动参数检查 检查JVM启动参数配置 -Xmx4g -Xms4g配置分析 JDK版本JDK 8GC选择未指定使用默认的ParallelGC堆内存最大和初始堆内存均为4GB 初步问题假设 怀疑点ParallelGC可能是问题根源 设计目标ParallelGC主要追求系统最大吞吐量权衡策略为了吞吐量优化会牺牲单次GC的暂停时间推测结论可能因此导致暂停时间过长 第一次优化尝试切换到G1GC 优化策略选择 选择G1垃圾收集器的理由 稳定性在JDK 8的新版本中G1已经相当稳定性能表现具有良好的延迟控制能力适用场景更适合低延迟要求的应用 配置过程 初次配置失败 # 参数配置错误导致启动失败 -Xmx4g -Xms4g -XX:UseG1GC -XX:MaxGCPauseMills50ms错误分析 参数名拼写错误MaxGCPauseMills → MaxGCPauseMillis参数值格式错误50ms → 50 修正后配置 -Xmx4g -Xms4g -XX:UseG1GC -XX:MaxGCPauseMillis50初步效果验证 服务启动成功通过健康检测切换到新节点后监控显示 G1GC初期效果监控图 效果评估 ✅ GC暂停时间基本控制在50ms以内✅ 符合预期达到了初期的优化目标 但是问题远未结束..... “彩蛋”惊喜 过了一段时间我们发现了个下面这个惊喜也许是惊吓如下图所示 中奖了运行一段时间后最大 GC 暂停时间达到了 1300ms。 情况似乎更恶劣了。 继续观察发现不是个别现象 内心是懵的觉得可能是指标算错了比如把 10s 内的暂停时间全部加到了一起。 注册 GC 事件监听 于是想了个办法通过 JMX 注册 GC 事件监听把相关的信息直接打印出来。 关键代码如下所示 // 每个内存池都注册监听 for (GarbageCollectorMXBean mbean : ManagementFactory.getGarbageCollectorMXBeans()) {if (!(mbean instanceof NotificationEmitter)) {continue; // 假如不支持监听...}final NotificationEmitter emitter (NotificationEmitter) mbean;// 添加监听final NotificationListener listener getNewListener(mbean);emitter.addNotificationListener(listener, null, null); }通过这种方式我们可以在程序中监听 GC 事件并将相关信息汇总或者输出到日志。 再启动一次运行一段时间后看到下面这样的日志信息 { duration:1869, maxPauseMillis:1869, promotedBytes:139MB, gcCause:G1 Evacuation Pause, collectionTime:27281, gcAction:end of minor GC, afterUsage:{ G1 Old Gen:1745MB, Code Cache:53MB, G1 Survivor Space:254MB, Compressed Class Space:9MB, Metaspace:81MB, G1 Eden Space:0}, gcId:326, collectionCount:326, gcName:G1 Young Generation, type:jvm.gc.pause }情况确实有点不妙。 这次实锤了不是 FullGC而是年轻代 GC而且暂停时间达到了 1869ms。 一点道理都不讲我认为这种情况不合理而且观察 CPU 使用量也不高。 找了一大堆资料试图证明这个 1869ms 不是暂停时间而只是 GC 事件的结束时间减去开始时间。 打印 GC 日志 既然这些手段不靠谱那就只有祭出我们的终极手段打印 GC 日志。 修改启动参数如下 -Xmx4g -Xms4g -XX:UseG1GC -XX:MaxGCPauseMillis50 -Xloggc:gc.log -XX:PrintGCDetails -XX:PrintGCDateStamps重新启动希望这次能排查出问题的原因。 运行一段时间又发现了超长的暂停时间。 分析 GC 日志 因为不涉及敏感数据那么我们把 GC 日志下载到本地进行分析。 定位到这次暂停时间超长的 GC 事件关键的信息如下所示 Java HotSpot(TM) 64-Bit Server VM (25.162-b12) for linux-amd64 JRE (1.8.0_162-b12),built on Dec 19 2017 21:15:48 by java_re with gcc 4.3.0 20080428 (Red Hat 4.3.0-8) Memory: 4k page, physical 144145548k(58207948k free), swap 0k(0k free) CommandLine flags: -XX:InitialHeapSize4294967296 -XX:MaxGCPauseMillis50 -XX:MaxHeapSize4294967296-XX:PrintGC -XX:PrintGCDateStamps -XX:PrintGCDetails -XX:PrintGCTimeStamps -XX:UseCompressedClassPointers -XX:UseCompressedOops -XX:UseG1GC 2020-02-24T18:02:31.8530800: 2411.124: [GC pause (G1 Evacuation Pause) (young), 1.8683418 secs][Parallel Time: 1861.0 ms, GC Workers: 48][GC Worker Start (ms): Min: 2411124.3, Avg: 2411125.4, Max: 2411126.2, Diff: 1.9][Ext Root Scanning (ms): Min: 0.0, Avg: 0.3, Max: 2.7, Diff: 2.7, Sum: 16.8][Update RS (ms): Min: 0.0, Avg: 3.6, Max: 6.8, Diff: 6.8, Sum: 172.9][Processed Buffers: Min: 0, Avg: 2.3, Max: 8, Diff: 8, Sum: 111][Scan RS (ms): Min: 0.0, Avg: 0.2, Max: 0.5, Diff: 0.5, Sum: 7.7][Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.3][Object Copy (ms): Min: 1851.6, Avg: 1854.6, Max: 1857.4, Diff: 5.8, Sum: 89020.4][Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.6][Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 48][GC Worker Other (ms): Min: 0.0, Avg: 0.3, Max: 0.7, Diff: 0.6, Sum: 14.7][GC Worker Total (ms): Min: 1858.0, Avg: 1859.0, Max: 1860.3, Diff: 2.3, Sum: 89233.3][GC Worker End (ms): Min: 2412984.1, Avg: 2412984.4, Max: 2412984.6, Diff: 0.5][Code Root Fixup: 0.0 ms][Code Root Purge: 0.0 ms][Clear CT: 1.5 ms][Other: 5.8 ms][Choose CSet: 0.0 ms][Ref Proc: 1.7 ms][Ref Enq: 0.0 ms][Redirty Cards: 1.1 ms][Humongous Register: 0.1 ms][Humongous Reclaim: 0.0 ms][Free CSet: 2.3 ms][Eden: 2024.0M(2024.0M)-0.0B(2048.0K) Survivors: 2048.0K-254.0M Heap: 3633.6M(4096.0M)-1999.3M(4096.0M)][Times: user1.67 sys14.00, real1.87 secs] 前后的 GC 事件都很正常也没发现 FullGC 或者并发标记周期但找到了几个可疑的点。 physical 144145548k(58207948k free)JVM 启动时物理内存 137GB空闲内存 55GB。[Parallel Time: 1861.0 ms, GC Workers: 48]垃圾收集器工作线程 48 个。 GC 日志中揭露了几个关键信息 user1.67用户线程耗时 1.67ssys14.00系统调用和系统等待时间 14sreal1.87 secs实际暂停时间 1.87sGC 之前年轻代使用量 2GB堆内存使用量 3.6GB存活区 2MB可推断出老年代使用量 1.6GBGC 之后年轻代使用量为 0堆内存使用量 2GB存活区 254MB那么老年代大约 1.8GB那么“内存提升量为 200MB 左右”。 这样分析之后可以得出结论 年轻代转移暂停复制了 400MB 左右的对象却消耗了 1.8s系统调用和系统等待的时间达到了 14s。JVM 看到的物理内存 137GB。推算出 JVM 看到的 CPU 内核数量 72个因为 GC 工作线程 72* 5/8 ~ 48 个。 看到这么多的 GC 工作线程我就开始警惕了毕竟堆内存才指定了 4GB。 按照一般的 CPU 和内存资源配比常见的比例差不多是 4 核 4GB、4 核 8GB 这样的。 看看对应的 CPU 负载监控信息 通过和运维同学的沟通得到这个节点的配置被限制为 4 核 8GB。 这样一来GC 暂停时间过长的原因就定位到了 K8S 的资源隔离和 JVM 未协调好导致 JVM 看见了 72 个 CPU 内核默认的并行 GC 线程设置为 72* 5/8 ~ 48 个但是 K8S 限制了这个 Pod 只能使用 4 个 CPU 内核的计算量致使 GC 发生时48 个线程在 4 个 CPU 核心上发生资源竞争导致大量的上下文切换。 处置措施为 限制 GC 的并行线程数量 事实证明打印 GC 日志确实是一个很有用的排查分析方法。 限制 GC 的并行线程数量 下面是新的启动参数配置 -Xmx4g -Xms4g-XX:UseG1GC -XX:MaxGCPauseMillis50 -XX:ParallelGCThreads4-Xloggc:gc.log -XX:PrintGCDetails -XX:PrintGCDateStamps这里指定了 -XX:ParallelGCThreads4为什么这么配呢我们看看这个参数的说明。 -XX:ParallelGCThreadsn设置 STW 阶段的并行 worker 线程数量。 如果逻辑处理器小于等于 8 个则默认值 n 等于逻辑处理器的数量。 如果逻辑处理器大于 8 个则默认值 n 大约等于处理器数量的 5/8。在大多数情况下都是个比较合理的值。如果是高配置的 SPARC 系统则默认值 n 大约等于逻辑处理器数量的 5/16。 -XX:ConcGCThreadsn设置并发标记的 GC 线程数量。默认值大约是 ParallelGCThreads 的四分之一。 一般来说不用指定并发标记的 GC 线程数量只用指定并行的即可。 重新启动之后看看 GC 暂停时间指标 红色箭头所指示的点就是重启的时间点可以发现暂停时间基本上都处于 50ms 范围内。 后续的监控发现这个参数确实解决了问题。 案例总结与思考 核心经验 通过这个完整的排查案例我们可以得到以下重要经验没有量化就没有改进。JVM问题排查和性能调优必须基于具体的监控数据进行。 使用的排查手段 本案例运用了以下关键技术手段 指标监控通过Micrometer Datadog建立完整的监控体系⚙️ JVM参数调优合理配置启动内存和垃圾收集器GC日志分析深入分析GC日志定位根本原因JMX事件监听通过编程方式获取详细的GC事件信息 GC性能维度评估 延迟维度 主要关注GC暂停时间目标最大暂停时间 200ms平均暂停时间 100ms 吞吐量维度 业务线程CPU资源占用百分比GC影响因素暂停时间 并发GC的CPU消耗 系统容量维度 硬件配置合理性服务处理能力匹配度 关键技术洞察 容器化环境的特殊挑战 容器资源限制与JVM感知的不匹配GC线程数配置需要与实际可用CPU核心数对齐K8s资源隔离机制需要与JVM参数协调配置 问题排查的系统性方法 现象观察 → 通过监控发现异常假设验证 → 基于经验提出问题假设深入分析 → 通过日志等手段验证假设解决方案 → 针对根因制定解决措施效果验证 → 持续监控验证解决效果 只要确保各项性能指标满足业务需求资源占用保持在合理范围内就达到了JVM调优的预期目标。
http://www.dnsts.com.cn/news/87345.html

相关文章:

  • 漳州网站建设到博大赞wordpress登录开发文档
  • 12380网站的建设情况永康网站开发公司
  • python在线免费网站网络设计应该考虑的原则有哪些
  • 接做网站私活北京数字智慧展厅设计咨询
  • 直播网站建设需要多少钱西安app开发制作公司
  • 上海工商网站网站前台模块包括什么
  • 2024免费推广网站cms企业网站系统
  • 官方网站开发用什么语言网页报价表
  • 如何对网站管理官方模板
  • 花生壳内网穿透网站如何做seo优化怎么查名字有没有被注册商标
  • 网站空间租赁软件开发平台建设
  • 免费asp网站源码下载医疗网站建设策划书
  • wordpress电子书主题浙江企业seo推广
  • 蚌埠网站建设公司cztv招聘网站对比这么做
  • 软文自助发稿软件开发 网站建设常州网站建设方案维护
  • 大学网站开发与管理知识总结有哪些网站可以做电子邀请函
  • 怎么在社保网站上做员工减少wordpress商城视频教程
  • 安徽淮北做网站的公司支持wordpress空间
  • 做网站页面视频教学wordpress登陆才可以看到
  • 网站注册会绑定式收费吗国家建筑网官网
  • 网站开发公司的义务nodejs网站开发实例
  • 企业管理培训课程有哪些快速排名seo
  • 农业网站建设源代码 ASP南京 网站备案
  • 图派科技做网站怎么样天津滨海新区大爆炸
  • 公司网站模板免费版阿迪达斯网站建设的总体目标
  • 有什么ae做动图的网站湖南省邵阳市建设局网站
  • 网络运营公司的经营范围海口seo网站推广
  • lua做网站wordpress 显示最新文章标题
  • 建设网站青岛唐山网站制作工具
  • 淘宝优惠劵网站怎么做中信建设有限责任公司杨建强