亲宝软件园·资讯

展开

.Net程序内存异常 .Net程序内存异常的原因及解决

dotNet源计划 人气:0
想了解.Net程序内存异常的原因及解决的相关内容吗,dotNet源计划在本文为您仔细讲解.Net程序内存异常的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:.Net程序内存异常,.Net程序内存异常解决,下面大家一起来学习吧。

一、概要

大概在今年三月份的时候突然被紧急调到另外一个项目组解决线上内存异常问题。经过两周的玩命奋战终于解决了这个问题这里把心路历程及思路分享给大家。希望可以帮助到各位或现在正遇到这样事情的小伙伴提供一些思路。

二、场景

当部门老大找到我的时候,给我描述了这样一段话。

“目前服务出现了提交内存异常的问题,目前分析出来可能是日志组件有大量的日志消息堆积把内存占满导致服务崩溃了。在国内某地区客户的服务器上15000台物联网设备不能正常工作这个问题非常紧急需要马上解决。”

问题描述至此,没有其他可用信息。这时候我先崩溃了...但是任务找到你不能说不行。万一解决了这种重大事故还能在部门老大面前秀一把。

三、思路

(1)分析

Part1,分析日志堆积原因

解决方案:

以为这样就结束了吗?不,当程序改好之后放在测试服务器上跑第二天早上测试部的小姐姐就找到我说异常报错情况是好了,但是内存泄漏还是没解决。

Part2,查找内存泄漏的根本原因

看来Part1的操作仅仅只是修复了一个小bug而已,并不是我所想的那么简单,在日志的查看中还发现log日志中出现“tcp服务拒绝连接XXX异常”。当我看到这些的时候心情糟糕透了....

1.一早我就用Profile把服务程序跑了一遍发现了

(1)有几个消息队列占用非常大,查阅代码之后发现服务端程序会和15000台物联网设备进行交互的所有数据都会先堆积到这个队列里如果这个队列满了(Queue上限被设定2w)会new新的Queue然后把溢出的部分转到新的Queue里,最可怕的是从队列里取数据的还是单线程处理。

(2)还会有很多磁盘I/O的操作会存储在应用服务器本机上例如socket通讯的报文和需要转发的内容等等都会进行写入操作。
(3)逐步调试的时候发现大部分的方法实现都是同步方法,而且框架版本居然是.net freamwork4。

解决方案:

(1)

【移除new新队列的机制、删除Main Queue的上限设置改为多线程处理Queue;一切数据堆积的本质就是数据处理不过来所以开辟再多的内存空间都是慢性死亡而已。】
【走访物联网硬件部门,询问物联网设备发送数据频率、设备数、单台设备发送单条数据的大小是多少KB;为什么需要了解?这些第一点在程序内记录日志然后统计成走势图能直接观察队列内部的变化开会的时候能给领导具有说服力的证据能看到数据量什么时候陡增、数据大小等;第二点因为这些报文数据需要存在应用服务器本地那么这时候就能计算出写入的数据量有没有超出普通硬盘的写入I/O瓶颈以及网络带宽的占用。】
【走访物联网硬件部门2,询问物联网设备socket传输数据时是否有走正常“tcp挥手”流程;为什么?因为socket tcp通讯中,是双工通道那么其中有一端突然断开,另一端会进入“wait”状态不会及时回收tcp连接资源,大家试想一下如果15000台设备高频短连接去操作那么服务端连接队列资源很有可能吃不消。这个时候就需要服务端主动断开“失效”连接及时回收资源“拆除双工通道”以及调整socket连接队列大小。】

(2)磁盘写入报文信息这块,就要用三寸不烂之舌说动项目经理把这块砍掉以节约CPU性能以及减少磁盘I/O,大伙试想一下每次socket通讯进行收发的时候都要去操作一下I/O那是多么恐怖的一件事情;最后沟通结果那个组的项目经理同意砍掉部分模块磁盘写入功能,那么问题来了剩下的怎么办如何将优势进一步扩大?这时候继续查阅项目代码,结果发现socket通讯中“收”、“发”都会操作一次。那么这时候需要做的是将报文积累到一定数量比如说积累1000条报文再一次性写入那么磁盘I/O的操作频率将成倍递减。

(3)最后一个问题,就是讲所有的方法修改为异步方法。这时候就能祭出Task、Async、Await了。但是基于的框架是.net freamwork4的,后来又去查阅MSDN的文档发现.net freamwork4远古框架中还是有这些特性的虽然用法稍微难受点但是还是能优化的。一定要记住一点,开发服务端要有“服务端”思维如果都是同步方法就会被同步阻塞处于“等待处理结果状态”这样的话服务端的并发量是上不去的。

这里虽然没怎么用上的一发大招,但是这里还是分享给大家“注释大法”;注释掉最有可能出问题的地方逐一排查一定能发现问题的所在就是非常的耗时那会我基本每天工作12小时,尤其是公司的远古项目通常“代码烂”、“设计基本没有”、“使用的.net框架版本低”等等,一堆恶心人的事情发生。

(2)工具

Part3,总结

基于以上的修改,在测试服务器上稳定运行3周内存稳定在2.9G左右;

一定要记住:

其实解决这个问题时期发生了很多有趣的故事,不过最终还是要解决难啃的问题证明自己,开发学习本身就是一个不断变强的过程“修技术,也修内心”当自己逐渐变强之后也不要鄙视技术不好的同事始终保持一颗学徒的心。

Part4,彩蛋

解决这个问题之后在同部门同事的眼里威望都会有提升(尤其是测试部门的小姐姐,因为她们不用费力的每天去看服务器了),最终解决项目的重大事故部门老大给了机会调到其他省的研发中心当项目经理薪资平移的基础上再上浮百分之十。可见掌握一手救急的技能有多么划算。

加载全部内容

相关教程
猜你喜欢
用户评论