开发那些事儿:EasyNTS内存泄露是什么原因?如何解决?
EasyNTS上云网关包含组网运维、多协议视频流拉转推等功能,它可以解决内网设备上云、内网业务上云、直播上云、运维上云等上云需求,通过端口穿透技术,可以将内网的任何网络设备,以IP+端口的形式发布到云端,让处于内网的设备成为一个“云设备”,帮助企业打造“虚拟云主机”。
有用户反馈,EasyNTS运行pprof一段时间后,内存持续增长。运行30个小时后,从启动时的1.2%飙升到33%,并在2周时间左右系统因内存而崩溃。我们对此情况立刻进行了排查与分析。
1)查看pprof,发现了几个占用内存较大的函数。
StatisticalFlow函数是用于统计流量输入输出的,每30秒执行一次,其中嵌套了多级for循环。每个循环里面还嵌套了网络请求及defer Body.CLose() 。
defer表示函数结束后执行,for循环表示函数永远不会结束,这就导致每30秒都有一定量的defer压入函数栈帧中,无限增大,无法释放。当函数栈不够用时,又去申请更大的内存空间,将旧的数据拷贝过去,并且一直重复这个过程。
从代码结构上来看也极其糟糕,在for循环里面嵌套了多个for循环,层级就有4级,如下图所示:
再看另外一个函数,记录设备下线日志,此处每个客户端会创建至少一个协程,并在for循环里每15秒创建一个无法回收的定时器。
在加载配置中,右侧调用可以看到有非常多的调用,每次调用都要重新加载配置。因为返回的是指针,会逃逸到堆上,直到垃圾回收才清理。
以上分析结果均是导致用户EasyNTS内存泄露的原因。根据以上分析,可通过以下办法解决内存问题:
1)删除defer,在资源使用完毕后立即关闭;
2)定时器创建在for循环外面;
3)重构函数,每个函数尽量不要超过60行;
4)配置相关使用单例模式。
EasyNTS上云网关可应用在多种场景中,如远程办公、在线课堂、虚拟直播等,当然也可以进行各种上云服务,如果大家还想了解更多相关内容,欢迎持续关注我们的更新,也欢迎大家联系我们探讨更多内容。
相关文章
- JVM内存与垃圾回收篇第3章运行时数据区概述及线程
- 存储类别、链接和内存管理(二)
- 内存频率有哪些?怎么看内存频率
- 面向对象Java开发——对象的内存原理和内存图
- [mit6.s081] 笔记 Lab5: Lazy Page Allocation | 内存页懒分配
- 宝塔版面内存太小,机器经常数据库自己停止,添加一个自动数据库任务再试试?
- 驱动开发:通过内存拷贝读写内存
- 驱动开发:内核MDL读写进程内存
- 嵌入式开发如何统计运行占据内存
- 驱动开发:内核MDL读写进程内存
- Android开发学习笔记之 获得Android 可使用内存
- Tina_Linux_内存优化_开发指南
- 【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )
- 【嵌入式开发】ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )
- 【Android 逆向】代码调试器开发 ( ptrace 函数 | 向进程内存写出数据 )
- 【Windows 逆向】OD 调试器工具 ( 显示模块窗口 | 显示记录窗口 | 显示内存窗口 | 显示线程 | 显示句柄 | 显示 CPU | 多窗口界面 )
- 修改android最小堆内存详解手机开发
- 文件Linux 内存中的文件映射磁盘(linux内存映射磁盘)
- java内存模型详解编程语言
- 观点:DDR内存即将谢幕 HBM 3/4内存才是未来
- Redis:利用内存加速数据存储(redis内存数据库)
- Oracle内存不断增加的负担(oracle内存不停增长)
- Redis超出内存的应对之策(redis超出内存策略)