丿本来无一物 發表於 2025-5-13 23:29:00

性能瓶颈诊断:我们是如何揪出 Dubbo 大对象传输这个“幕后黑手”?

<p>本文已收录在Github,<strong>关注我,紧跟本系列专栏文章,咱们下篇再续!</strong></p>
<ul>
<li>🚀 魔都架构师 | 全网30W技术追随者</li>
<li>🔧 大厂分布式系统/数据中台实战专家</li>
<li>🏆 主导交易系统百万级流量调优 &amp; 车联网平台架构</li>
<li>🧠 AIGC应用开发先行者 | 区块链落地实践者</li>
<li>🌍 以技术驱动创新,我们的征途是改变世界!</li>
<li>👉 实战干货:编程严选网</li>
</ul>
<h2 id="0-确认问题现象接口响应时间飙升">0 确认问题(现象):接口响应时间飙升</h2>
<p>某接口平时响应时间平均在200ms,但是最近飙升到600ms。</p>
<h2 id="1-自顶向下排除法">1 自顶向下,排除法</h2>
<h3 id="11-系统层监控查看-cpu-tcp-连接-网卡-load-等">1.1 系统层(监控):查看 CPU, TCP 连接, 网卡, Load 等</h3>
<p>查看监控指标,cpu、tcp连接、网卡、load一切正常</p>
<h3 id="12-应用运行时层gc内存">1.2 应用运行时层(GC、内存)</h3>
<h4 id="分析gc日志查看-full-gc-情况">分析gc日志:查看 Full GC 情况</h4>
<pre><code>2017-01-25T11:02:21.939+0800: 71437.958: 2838587K-&gt;264180K(4114432K) , 0.2832510 secs]

2017-01-25T11:06:04.727+0800: 71660.746: 2825492K-&gt;262440K(4112384K) , 0.2960190 secs]

2017-01-25T11:09:28.385+0800: 71864.404: 2816719K-&gt;276325K(4045824K) , 0.3055130 secs]

2017-01-25T11:13:33.216+0800: 72109.235: 2814470K-&gt;233175K(4121088K) , 0.2411000 secs]
2017-01-25T11:17:44.210+0800: 72360.229: 2852072K-&gt;265640K(4082688K) , 0.2892200 secs]
2017-01-25T11:21:59.963+0800: 72615.982: 2820573K-&gt;245655K(4107264K) , 0.2480330 secs]
2017-01-25T11:25:45.380+0800: 72841.398: 2829177K-&gt;284318K(4059136K) , 0.3346010 secs]
2017-01-25T11:29:39.537+0800: 73075.556: 2800304K-&gt;240992K(4112384K) , 0.2763920 secs]
2017-01-25T11:33:36.363+0800: 73312.381: 2837223K-&gt;264429K(4105728K) , 0.2834540 secs]
2017-01-25T11:37:42.528+0800: 73558.547: 2822955K-&gt;262562K(4090880K) , 0.2769620 secs]
2017-01-25T11:41:38.613+0800: 73794.632: 2845190K-&gt;280961K(4108800K) , 0.3233140 secs]
2017-01-25T11:45:24.406+0800: 74020.425: 2794811K-&gt;254403K(4098048K) , 0.2702330 secs]
2017-01-25T11:49:17.728+0800: 74253.746: 2865780K-&gt;325470K(4043264K) , 0.3316160 secs]
2017-01-25T11:53:02.996+0800: 74479.015: 2814606K-&gt;263508K(4093440K) , 0.2693080 secs]
2017-01-25T11:56:29.604+0800: 74685.623: 2775634K-&gt;609246K(4101632K) , 0.9831970 secs]
2017-01-25T11:59:01.868+0800: 74837.887: 2884472K-&gt;433632K(4084224K) , 0.7554340 secs]
2017-01-25T12:01:48.453+0800: 75004.472: 2771719K-&gt;266286K(4044288K) , 0.3109250 secs]
2017-01-25T12:04:36.500+0800: 75172.519: 2818034K-&gt;232197K(4096000K) , 0.2387330 secs]
</code></pre>
<p>整理25号其中一台机器的gc日志,过滤了FullGC的日志,都是STW操作,不过从日志可看出:</p>
<ul>
<li>年轻代完全会被回收</li>
<li>老年代也会回收90%,基本每次回收90%</li>
</ul>
<p>永久代没变化,但永久代在参数配的512M空间是足够的。目前才80M的永久代已足够用。另外老年代回收之后的HEAP空间也回收明显~~90%左右,heap的总容量也是足够的啦。看来JVM也无需优化。</p>
<h4 id="内存分析">内存分析</h4>
<p>查看内存分布图,检查大对象</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/other/1097393/202505/1097393-20250513232927371-1662562278.jpg" class="lazyload"></p>
<p>从分布图可以看出,内存中剩余空间还是很大的。并且没有特别大的对象存活,百分比最高的也仅tomcat的webclassloader,无非请求数太多造成单例比较多,这不会影响接口速度。</p>
<h3 id="13-应用自身核心性能层压测">1.3 应用自身核心性能层(压测)</h3>
<p>之前的步骤排查了系统基础资源和应用 JVM 自身的健康状况。但应用是在复杂的生产环境中运行的,可能受到外部流量、依赖服务、网络等因素的影响。通过将流量隔离到一台机器并进行内网压测,可以测试应用在排除外部干扰、仅自身处理请求时的表现。</p>
<p>使负载均衡不会打到线上机,内网进行压测重现:</p>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/other/1097393/202505/1097393-20250513232928296-229154437.jpg" class="lazyload"></p>
<p>从报告可看出,压测一切正常,响应最高也就260ms。压测结果显示,在隔离环境下,应用的响应时间正常。这是一个非常重要的发现!它强力证明:</p>
<ol>
<li>应用自身的核心处理逻辑在正常负载下是高效的。</li>
<li>问题 <strong>不在</strong> 应用代码本身的计算效率低下或内存分配问题。</li>
<li>问题 <strong>在于</strong> 应用在 <strong>生产环境</strong> 中,与 <strong>外部</strong> 某些组件或数据交互时出现了瓶颈。 这个结论将排查方向彻底从应用自身代码和 JVM 状态转移到其 <strong>依赖项</strong> 或 <strong>外部接口</strong>。</li>
</ol>
<h3 id="14-依赖层redisdubbo">1.4 依赖层(Redis、Dubbo)</h3>
<h4 id="查看redis监控">查看redis监控</h4>
<p>既然问题出在与外部交互,Redis 是一个常见的依赖(缓存或数据存储)。检查 Redis 的监控,特别是 I/O 情况,是排查依赖服务性能的标准步骤。</p>
<p>发现不是redis造成的,io都正常。</p>
<p>Redis 监控正常,排除了 Redis 作为瓶颈的可能性。排查范围进一步缩小。此时需要考虑其他依赖,特别是那些与该接口直接相关的外部通信。</p>
<h4 id="分析dubbo日志">分析Dubbo日志</h4>
<p>既然是接口响应慢,而且 Redis 等常见依赖排查过了,那么检查该接口通过 Dubbo 进行的输入/输出通信日志就变得至关重要。特别是要关注 RPC 调用的耗时和传输的数据量。</p>
<p>因为本服务需要给外部提供远程RPC服务。</p>
<p>通过awk统计Dubbo日志发现在请求某些数据的时候返回值过大,基本上达到了8M到12M,导致了dubbo在传输大对象时造成了时间过长,从而影响了Dubbo的接口响应时间飙升至600ms。</p>
<p>Dubbo 日志揭示了在处理某些请求时,返回值异常大(8-12MB)。这个发现与响应时间飙升的现象直接关联了起来。大数据量的网络传输本身就需要时间,而且可能涉及序列化/反序列化开销,完全有可能导致 RPC 调用耗时显著增加,进而拉高接口的整体响应时间。这几乎确定了问题的根源。</p>
<h2 id="2-解决">2 解决</h2>
<p>和调用方沟通,把对方需要的字段留下,其他字段去掉,进行瘦身。发布之后,一切正常。</p>
<h2 id="3-总结">3 总结</h2>
<p>确认问题 (现象)、自顶向下,排除法,并继续结合 :</p>
<ul>
<li>聚焦与问题相关的关键点:结合接口的特性(提供了 Dubbo 服务),将排查重点放在了 Dubbo 通信上</li>
<li>分析具体交互数据:在关键点 (Dubbo) 上,分析具体的数据和调用细节,发现了异常的大数据量</li>
<li>连接现象与根源:大数据量传输耗时 -&gt; Dubbo 调用变慢 -&gt; 接口响应变慢。形成完整的因果链条</li>
<li>基于根源解决问题:对症下药,通过瘦身数据来解决传输瓶颈</li>
</ul>
<blockquote>
<p>本文由博客一文多发平台 OpenWrite 发布!</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/JavaEdge/p/18875082
頁: [1]
查看完整版本: 性能瓶颈诊断:我们是如何揪出 Dubbo 大对象传输这个“幕后黑手”?