.net 奇葩问题调试经历之3——使用了grpc通讯类库后,内存一直增长......
引言
在分布式系统开发中,gRPC 作为一种高性能、开源的远程过程调用(RPC)框架,被广泛应用于构建高效的服务间通信。
我们的项目也不例外,利用 gRPC 实现了多个微服务之间的通信。然而,在系统上线并经过一段时间的运行后,我们遇到了一个棘手的问题 —— 内存占用持续增长,虽然并没有影响到系统的性能和稳定性。但在测试人员的眼里,就是一个致命的问题,测试通不过,版本就会被打回,怎么办?
当然需要排查问题,查找根源了。
1. 问题发现
我们的系统由多个基于.NET 开发的微服务组成,通过 gRPC 进行通信。
在日常的系统监控中,我们注意到其中一个核心微服务的内存占用呈现出持续上升的趋势。
起初,这种增长较为缓慢,并未引起我们的足够重视。但随着时间的推移,内存占用不断攀升,导致服务器的资源逐渐紧张,系统响应时间变长,甚至出现了偶尔的卡顿现象。
为了更直观地了解内存增长情况,我们使用了性能监控工具,
通过这些工具,我们绘制了内存使用情况的时间序列图,清晰地看到内存占用曲线几乎是一条不断上升的斜线。这表明内存泄漏问题的存在,我们必须尽快找到根源并解决,否则系统可能会因为内存耗尽而崩溃。
2.排查排查
首先怀疑是代码中存在内存泄漏的漏洞。
为进一步深入剖析内存问题,借助内存分析工具。在.NET 生态系统中,有诸如 dotMemory 和 CLR Profiler 等强大的内存分析工具可供选用。我们最终选择了 dotMemory 进行内存分析。
先在开发环境中对出现内存问题的微服务进行内存快照。通过 dotMemory 的可视化界面,查看内存中的对象分布状况,试图找出那些占用大量内存的对象类型。
一些与 gRPC 通信相关的对象在内存中数量众多,且随着时间不断增多。比如,gRPC 的元数据(Metadata)对象以及一些请求 / 响应消息对象。
然而,仅仅知晓这些对象在内存中大量存在,还不足以确定问题的根源。
发布评论