.Net程序内存异常的原因及解决
这篇文章主要介绍了解决.Net程序内存异常问题的过程及思路。
一、概要
今年三月份,我被紧急调到一个项目组,去解决线上内存异常问题。经过两周的艰苦奋战,终于解决了这个问题。在这里,我想分享一下我的心路历程和思路,希望能帮助到正在面临类似问题的朋友们。
二、场景
当时,部门领导描述了一个问题:服务出现了提交内存异常,可能是日志组件堆积了大量日志消息,占满了内存,导致服务崩溃。特别是在某客户的服务器上,15000台物联网设备不能正常工作,情况非常紧急。
面对这个问题,我首先分析了日志堆积的原因。通过查看日志文件,我发现主要是报错情况,如x对象为null,对象转换失败等。日志组件的实现也存在一些问题,比如Log对象在每个调用的类里都会重新创建。
三、解决方案
针对这些问题,我提出以下解决方案:
1. 修复对象为null的问题,并加上空值判断。在json值转换时,如果传入的值是null,就会引发连锁反应。为了避免这种情况,我们需要在程序中加入判断,尽量避免触发try机制,以提高程序性能。
2. 重构日志组件为单例且线程安全的实现。将日志的数据结构体改为struct,以减少内存占用并提高处理速度。
当程序改好后放在测试服务器上运行时,虽然异常报错情况有所改善,但内存泄漏问题仍未解决。于是,我继续深入查找内存泄漏的根本原因。
在查看日志时,我发现log日志中出现“tcp服务拒绝连接XXX异常”。这使我意识到问题可能不仅仅在于日志堆积。进一步分析服务程序后,我发现了以下几个问题:
1. 有几个消息队列占用非常大,服务端程序与15000台物联网设备进行交互的所有数据都会堆积在队列里。如果队列满了,会创建新的Queue,然后把溢出的部分转到新的Queue里。更严重的是,从队列里取数据的操作是单线程的。
2. 存在很多磁盘I/O操作,例如socket通讯的报文和需要转发的内容等都会进行写入操作。
3. 调试时发现大部分方法实现都是同步方法,而且使用的框架版本居然是.NET framework 4。
针对这些问题,我提出以下解决方案:
1. 移除创建新队列的机制,删除Main Queue的上限设置,改为多线程处理Queue。数据堆积的本质是数据处理不过来,所以开辟再多的内存空间也无法解决问题。我们需要从处理数据的效率入手,提高处理速度。
2. 了解物联网设备的发送数据频率、设备数量以及单台设备发送数据的大小。这些信息可以帮助我们观察队列内部的变化,并在开会时给出具有说服力的证据。这些报文数据需要存储在应用服务器本地,因此我们需要计算写入的数据量是否超出硬盘的I/O瓶颈及网络带宽的占用。
3. 了解物联网设备在socket传输数据时是否走正常的“tcp挥手”流程。因为socket tcp通讯是双工通道,如果一端突然断开,另一端会进入“wait”状态,不会及时回收tcp连接资源。如果15000台设备高频短连接去操作,服务端连接队列资源很可能吃不消。我们需要确保设备的socket传输遵循正常的tcp握手和挥手流程。
在数字化浪潮中,服务端程序的稳定性和效率至关重要。面对“.Net程序内存异常”这一棘手问题,我们不得不深入剖析并解决这一难题。在这场挑战中,我们不仅要运用技术知识,还要展现出解决问题的决心和毅力。
(一)资源回收与“双工通道”拆除
当服务端连接出现“失效”时,我们需要主动断开这些连接,及时回收资源。这就像拆除一座城市的“双工通道”,以优化交通流量。调整socket连接队列大小,确保系统在高并发下依然稳定。这不仅需要技术层面的调整,更需要我们对系统架构有深入的理解。
(二)优化磁盘I/O与报文处理
磁盘写入报文信息是一项消耗资源的工作。为了节约CPU性能并减少磁盘I/O,我们需要说服项目经理砍掉部分模块。但剩下的工作如何进一步优化呢?通过查阅项目代码,我们发现socket通讯每次“收”、“发”都会操作一次I/O。于是,我们决定积累一定数量的报文后再一次性写入,这样磁盘I/O的操作频率将大大减少。这个过程考验我们的代码优化能力和逻辑思维能力。
(三)异步方法与任务优化
为了让服务端程序更高效,我们将所有的方法修改为异步方法。利用Task、Async、Await等特性,我们可以提高程序的并发处理能力。虽然我们的框架是较旧的“.freamwork4”,但通过查阅MSDN文档,我们依然找到了优化的方法。记住,开发服务端要有“服务端”思维,同步阻塞会限制服务端的并发量。在这个过程中,我们不仅要掌握技术知识,还要学会如何与团队沟通合作。
(四)工具的运用与问题分析
在解决问题的过程中,我们运用了多种工具来辅助分析。Visual Studio的Profile可以分析CPU、内存等占用情况;VMMap也是一个很好的分析工具;ANTS Performance Profiler能逐级告诉你内存占用的地方以及内存占用大小;还有Windows操作系统自带的资源监视器,这些都是我们的得力助手。通过这些工具,我们能够快速定位问题并找到解决方案。
(五)成果与经验分享
经过一系列的修改和优化,我们的程序在测试服务器上稳定运行了3周,内存稳定在2.9G左右。这个过程让我们深刻体会到解决问题的成就感。我们也明白遇到问题时应该冷静思考、积极寻找解决方案。在这个过程中,我们不断提升自己的技术水平和解决问题的能力,最终得到了同事和上级的认可。我们还获得了调到其他省的研发中心担任项目经理的机会,薪资也得到了上浮。这让我们更加坚信掌握一手救急的技能是非常有价值的。
以上就是关于.Net程序内存异常的原因及解决的详细内容。在解决问题的过程中,我们不仅提升了自己的技术能力,还积累了宝贵的经验。希望这篇文章能对你有所帮助,更多关于.Net程序内存异常的资料请关注狼蚁SEO的其它相关文章!
编程语言
- .Net程序内存异常的原因及解决
- 为PHP模块添加SQL SERVER2012数据库的步骤详解
- Angular4表单验证代码详解
- PHP实现对文本数据库的常用操作方法实例演示
- Vue头像处理方案小结
- jQuery实现下拉菜单的实例代码
- js es6系列教程 - 基于new.target属性与es5改造es6的类
- 微信小程序入口场景的问题集合与相关解决方法
- TP5框架实现签到功能的方法分析
- 详解如何使用 vue-cli 开发多页应用
- YII2框架中日志的配置与使用方法实例分析
- 基于JS实现回到页面顶部的五种写法(从实现到增
- AngularJS控制器之间的通信方式详解
- 使用veloticy-ui生成文字动画效果
- 微信小程序自定义底部导航带跳转功能
- Javascript之面向对象--封装