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

目录
  • 一、概要
  • 二、场景
  • 三、思路
    • (1)分析
      • Part1,分析日志堆积原因
      • Part2,查找内存泄漏的根本原因
    • (2)工具
      • Part3,总结
      • Part4,彩蛋

一、概要

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

二、场景

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

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

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

三、思路

(1)分析

Part1,分析日志堆积原因

  • 拿到服务器地址去翻出日志文件,查看日志内容;内容基本上都是一些报错情况xxx对象为null,对象转换失败。
  • 日志组件的实现也比较糟糕Log对象在每个调用的类里都会重新new

解决方案:

  • 修复对象为null的问题并加上空值判断,大概的原因就是json值转换的时候传入的值是null那么就引起这两块的连锁反应。非常值得注意的一点是通常json对象转换的地方都会加入try块去捕获异常在程序里try的捕捉是会对.net程序造成性能影响的所以能用判断规避的尽量不要去触发try机制,程序性能被拖下去其他方面的处理就会变相的削减处理速度变慢那么数据堆积好像就解释的通了。
  • 将日志组件重构为单例且线程安全的实现,写入日志的数据结构体是class这里改成struct,考虑的因素是引用类型会存在引用问题再就是考虑的值类型和引用类型在内存中占用的大小是不一样的,而且值类型和引用类型在处理速度上值类型更快。

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

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)工具

  • Visual Studio自带的Profile。【可以分析CPU、内存等占用情况;这款比较推荐】
  • VMMap【可以分析CPU、内存等占用情况】
  • ANTS Performance Profiler【这款工具比较强大能分析调用链路逐级告诉你内存占用的地方以及内存占用大小】
  • Window操作系统自带的资源监视器这个不用多说大家都会用。

Part3,总结

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

一定要记住:

  • “遇到任何棘手的事情不要抱怨。”
  • “一个优秀的软件工程招聘进来就是解决问题的,而不是制造问题;”
  • “对于任务的安排,高手永远都是说出解决问题的期限;到点交东西。而不是支支吾吾说不清楚、退缩。”
  • “遇到问题冷静思考,相信自己一定可以的;那怕失败去尝试一下也好。”
  • “没解决问题的时候不要说任何话,说什么都像是在找理由。闭上嘴巴去想办法。”

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

Part4,彩蛋

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

以上就是.Net程序内存异常的原因及解决的详细内容,更多关于.Net程序内存异常的资料请关注我们其它相关文章!

(0)

相关推荐

  • 分析Netty直接内存原理及应用

    一.通常的内存模型概述 一般地,系统为了保证系统本身的安全性和健壮性,会将内存从逻辑上隔离成内核区域和用户区域,这很容易理解.因为用户行为不可控性太强,暴露得太多,就容易导致各种神奇的用法,超出系统的控制范围.当然,有的语言是支持直接控制内存的,比如C, 你可以用一个指针,访问内存中的几乎任意位置的数据(除了一些硬件地址).而像汇编,则可以访问任意地址.而这些底层的语言,已经离我们越来越远了,它基本上和普通程序员关系不大了. 用户很多时候的编程控制,都是在用户区域进行的,比如我做一些加减乘除,如

  • Net内存管理五大基础

    目录 1.小对象怎么处理的? 2.较大的对象会怎样? 3.垃圾收集器可以在不同的模式下运行以优化性能 4.引用不足会在性能和内存效率之间折衷 5.对象固定可以创建在托管和非托管代码之间传递的引用 1.小对象怎么处理的? 小型.NET对象被分配到小型对象堆(SOH)上.其中有3种:第0代,第1代和第2代.对象根据其寿命向上移动. 将新对象放在Gen 0上.当Gen 0充满时,.NET垃圾收集器(GC)运行,处理不再需要的对象,并将其他所有内容移至Gen1.如果Gen 1充满,则GC再次运行,也可以

  • asp.net中C#实现手动回收内存的方法

    C#有自动回收内存的机制,但是有时自动回收有一定滞后,需要在变量使用后迅速回收,节约内存,这里介绍一个最简单的方法. 1.先对对象赋值 null; 2.使用System.GC.Collect() 复制代码 代码如下: class Program {          static void Main(string[] args)          {              long lenth = 1024 * 1024 * 128;                GetCost("程序启动

  • 基于.NET BitmapImage 内存释放问题的解决方法详解

    网上查到的代码,多数的写法使用MemoryStream来实现: 复制代码 代码如下: new Thread(new ThreadStart(() => {    var bitmap = new BitmapImage();    bitmap.BeginInit(); using (var stream = new MemoryStream(File.ReadAllBytes(...))) {        bitmap.StreamSource = stream;        bitmap

  • asp.net动态产生checkbox(数据源为DB或内存集合)

    之前在网上看了很多,其实有一些也是大同小异,本人在此小编一下大致解决方案摒弃微软提供的CheckBoxList 需求: 1动态产生一组checkbox(数据源为DB或内存集合) 2post提交时后台能及时获取 3提交后刷新页面checkbox保持原先选中或取消选中状态 4避免产生大量的viewstate 方案:使用repeater+input(checkbox)+input(hidden) html代码 复制代码 代码如下: <asp:Repeater runat="server"

  • .Net Core内存回收模式及性能测试对比分析

    .NET Core 两种GC模式: Server GC / Workstation GC Server GC : 主要应用于多处理器系统,并且作为ASP.NET Core宿主的默认配置.它会为每个处理器都创建一个GC Heap,并且会并行执行回收操作.该模式的GC可以最大化吞吐量和较好的收缩性.这种模式的特点是初始分配的内存较大,并且尽可能不回收内存,进行回收用时会很耗时,并进行内存碎片整理工作.用一句简单的话说,这个就是贪婪模式,通过尽可能多的获得内存和少回收来得到更好的性能.结果就是高内存使

  • asp.net 获取机器硬件信息(cpu频率、磁盘可用空间、内存容量等)

    复制代码 代码如下: using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; usi

  • 一篇文章教你如何排查.NET内存泄漏

    目录 前言 检查托管内存使用 生成dump文件 分析 core dump 总结 前言 内存泄漏通常表示:一个应用程序的某些对象在完成它的的生命周期后,由于它被其他对象意外引用,导致后续gc无法对它进行回收,长此以往就会导致程序性能的下降以及潜在的 OutOfMemoryException. 这篇我们通过一个内存泄漏工具对 .NET Core 程序进行内存泄漏分析,如果程序是跑在windows上,那直接可以使用 Visual Studio 进行诊断. 检查托管内存使用 在开始分析内存泄漏之前,你一

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

    目录 一.概要 二.场景 三.思路 (1)分析 Part1,分析日志堆积原因 Part2,查找内存泄漏的根本原因 (2)工具 Part3,总结 Part4,彩蛋 一.概要 大概在今年三月份的时候突然被紧急调到另外一个项目组解决线上内存异常问题.经过两周的玩命奋战终于解决了这个问题这里把心路历程及思路分享给大家.希望可以帮助到各位或现在正遇到这样事情的小伙伴提供一些思路. 二.场景 当部门老大找到我的时候,给我描述了这样一段话. "目前服务出现了提交内存异常的问题,目前分析出来可能是日志组件有大量

  • Java 内存溢出的原因和解决方法

    你是否遇到过Java应用程序卡顿或突然崩溃的情况?您可能遇到过Java内存泄漏.在本文中,我们将深入研究Java内存泄漏的确切原因,并推荐一些最好的工具来防止内存泄漏发生. 什么是JAVA内存泄漏? 简单地说,Java内存泄漏是指对象不再被应用程序使用,而是在工作内存中处于活动状态. 在Java和大多数其他编程语言中,垃圾收集器的任务是删除不再被应用程序引用的对象.如果不选中,这些对象将继续消耗系统内存,并最终导致崩溃.有时java内存泄漏崩溃不会输出错误,但通常错误会以java.lang.Ou

  • Android内存泄漏的原因及解决技巧

    正确的生命周期管理如何防止Android内存泄漏 OutOfMemoryException是一个常见的令人沮丧的错误,也是导致应用程序意外关闭的主要原因之一. "如果应用程序昨天运行良好,为什么现在会发生这种情况?这个问题让Android的开发者和新手都感到困惑. 导致OutOfMemory异常的潜在原因有很多种,但其中最常见的是内存泄漏-应用程序中的内存分配从未释放.本文将解释如何通过有效的生命周期管理(开发过程中一个重要但经常被忽视的部分)来最小化这种风险. 为什么安卓系统会发生内存泄漏?

  • tomcat6下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法

    1.在tomcat6.0下jsp出现getOutputStream() has already been called for this response异常的原因和解决方法 在tomcat6.0下jsp中出现此错误一般都是在jsp中使用了输出流(如输出图片验证码,文件下载等),没有妥善处理好的原因. 具体的原因就是: 在tomcat中jsp编译成servlet之后在函数_jspService(HttpServletRequest request, HttpServletResponse res

  • JAVA程序内存溢出问题原因分析

    本文较为详细的分析了JAVA程序内存溢出问题原因.分享给大家供大家参考.具体如下: 遇到一个线上系统报 java.lang.OutOfMemoryError: PermGen space 错误,需要定位一下问题.很久之前到时弄过这个,现在还真有点不记得了,但这个真的是一个非常有意思的问题,值得好好研究一下.首先第一反应当然是加上-XX:+PrintGCDetails参数来看具体的GC日志,但是由于程序是tomcat启动的,担心里面封装的东西太多不好定位,既然在windows下面,所以还是借助可视

  • java迭代器移除元素出现并发修改异常的原因及解决

    迭代器(Iterator的对象)主要用于遍历集合,体现的就是迭代器模式. Iterator接口定义了以下四种方法. boolean hasNext():如果集合还没遍历完就返回true. Object next():返回集合里的下一个元素. void remove():删除集合里上一次next方法返回的元素. void forEachRemaining(Consumer action):这是java8新增的默认方法,可用Lambda表达式遍历数组. 使用迭代器遍历元素时不能不能通过Collect

  • Kotlin遍历集合导致并发修改异常的原因和解决方法

    各位android 老司机们,对于android 遍历结合的时候,发生并发修改异常一定毫不陌生: 之前看到过一篇文章, 在阿里巴巴Java开发手册中,有这样一条规定: 其实,增强for循环也是Java给我们提供的一个语法糖,如果将以上代码编译后的class文件进行反编译(使用jad工具)的话,可以得到以下代码: 1.原因:(其实我都不想在各位老司机面前再赘述这个了.-_-||) 这个异常产生的原因是,迭代器依赖于集合而存在,在判断成功后,集合中添加了新的元素,而迭代器并不知道,所有就报错了.其实

  • Java 常见的几种内存溢出异常的原因及解决

    内存溢出的异常有很多,并且每种内存溢出都会有不同的异常信息和解决方式,下面会列出常见的几种内存溢出异常 堆内存溢出 java.lang.OutOfMemoryError: Java heap space 原因: 当堆内存不足,并且已经达到JVM设置的最大值,无法继续申请新的内存,存活的对象在堆内存中无法被回收,那么就会抛出该异常,表示堆内存溢出. 当一次从数据库查询大量数据,堆内存没有足够的内存可以存放大量的数据 大量的强引用对象在堆内存中存活,GC无法回收这些对象,新创建的对象在新生代无法进行

  • Asp.Net 程序错误Runtime Error原因与解决

    Runtime Error Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewe

  • 文件路径正确,报java.io.FileNotFoundException异常的原因及解决办法

    新添加个发文类型 insert into mis.zyb_sf_type values('121','榆财法字','榆财法字',2,'0','1',21,NULL,'0','发文模板.doc','') 创建文章时出错了, 异常信息: 文件保存失败 Java.io.FileNotFoundException: E:\tomcat\jinzhongshi\jinzs_yuci\webapps\myDoJZS\word\template_fw\发文模版.doc (系统找不到指定的文件.) at jav

随机推荐