记一次 .NET 某市附属医院 Web程序 偶发性CPU爆高分析

一:背景

1. 讲故事

这个月初,一位朋友加微信求助他的程序出现了 CPU 偶发性爆高,希望能有偿解决一下。

71af6ba7847b3bc2a20a2c918ddc44fb.png

从描述看,这个问题应该困扰了很久,还是医院的朋友给力,开门就是 100块 红包 🤣🤣🤣,那既然是偶发性爆高,人工不行,还得用 procdump 自动抓,用 procdump -ma -s 5 -n 2 -c 70 w3wp 埋伏好,几天后如愿生成了两个dump,太妙了,接下来就用 windbg 分析吧。

二:Windbg 分析

1. 真的是cpu爆高吗

一切只相信数据,这里用 !tp 看一下此时 machine 的cpu值。

0:062:x86> !tp
CPU utilization: 83%
Worker Thread: Total: 37 Running: 6 Idle: 31 MaxLimit: 8191 MinLimit: 4
Work Request in Queue: 0
--------------------------------------
Number of Timers: 2
--------------------------------------
Completion Port Thread:Total: 1 Free: 1 MaxFree: 8 CurrentLimit: 1 MaxLimit: 1000 MinLimit: 4

从数据看,此时 CPU utilization: 83%, 没毛病。

2. 查看线程耗时

既然是偶发性的bug,而且也说了可能是医生操作了什么触发了什么条件才导致的,刚好这里也有 2 个dump,那就比一下各个线程的耗时吧,这里只提取 top5 。

0:062:x86> .time
Debug session time: Thu Dec 16 14:31:45.000 2021 (UTC + 8:00)
System Uptime: not available
Process Uptime: 0 days 1:20:48.000Kernel time: 0 days 0:08:43.000User time: 0 days 1:08:19.0000:062:x86> !runawayUser Mode TimeThread       Time62:7188     0 days 0:18:05.34344:6c90     0 days 0:16:16.68739:86e8     0 days 0:14:57.73432:1d8c     0 days 0:01:02.54635:23a4     0 days 0:00:58.2500:062:x86> .time
Debug session time: Thu Dec 16 14:32:00.000 2021 (UTC + 8:00)
System Uptime: not available
Process Uptime: 0 days 1:21:03.000Kernel time: 0 days 0:08:45.000User time: 0 days 1:08:41.0000:062:x86> !runawayUser Mode TimeThread       Time62:7188     0 days 0:18:11.87544:6c90     0 days 0:16:23.15639:86e8     0 days 0:15:04.15632:1d8c     0 days 0:01:02.54635:23a4     0 days 0:00:58.250

从信息看,间隔15s的dump,相对来说 62,44,39 这三个线程耗时最多,所以这三个线程值得继续挖一挖。

3. 查看线程栈

接下来用 ~62s; !clrstack;~44s; !clrstack;~39s; !clrstack 切到这三个线程看下栈情况,如下图所示:

a8654ce652297fe247c8d8f7aecd5c96.png

从栈中看,并没有用户代码,这就很尴尬了,我一度怀疑是不是 webform 的同步上下文导致的,但好歹我还是有一些经验,既然 !clrstack 看不到,那就用 !dumpstack

0:062:x86> !dumpstack
OS Thread Id: 0x7188 (62)
TEB information is not available so a stack size of 0xFFFF is assumed
Current frame: (MethodDesc 6b0e1b58 +0x1c System.Collections.Generic.ObjectEqualityComparer`1[[System.__Canon, mscorlib]].Equals(System.__Canon, System.__Canon))
ChildEBP RetAddr  Caller, Callee
3867ebfc 6b440484 (MethodDesc 6b0db558 +0x54 System.Collections.Generic.List`1[[System.__Canon, mscorlib]].Contains(System.__Canon))
3867ec18 24bbc3c5 (MethodDesc 25e2ba88 +0x845 xxx.bl_baseInfo.getBljl(System.String, System.String)), calling 2f23072e
3867ec84 6b466d0b (MethodDesc 6b0dcb5c +0x7b System.String.TrimHelper(Int32)), calling (MethodDesc 6b0d1cf4 +0 System.Globalization.CharUnicodeInfo.IsWhiteSpace(Char))
3867ec98 24bbba00 (MethodDesc 2a6eca54 +0x1b8 xxx_blcx.Button1_Click(System.Object, System.EventArgs)), calling (MethodDesc 25e2ba88 +0  xxx.getBljl(System.String, System.String))
3867ecb8 05b5d487 05b5d487
3867ecec 6092da13 (MethodDesc 5fdff5c0 System.Web.UI.WebControls.Button.OnClick(System.EventArgs))
3867ed04 5ffdd1cd (MethodDesc 5fdff5e8 +0xcd System.Web.UI.WebControls.Button.RaisePostBackEvent(System.String))
3867ed1c 5ffdd0fd (MethodDesc 5fdff5e0 +0xd System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(System.String))
...

真是太奇怪了,用户代码 xxx.bl_baseInfo.getBljl 怎么跑到非托管栈 ? 这真是第一次遇到,从栈上看,程序在 xxx.bl_baseInfo.getBljl() 方法中遇到了问题,接下来用 !dso 把堆对象都导出来。

0:062:x86> !dso
Error requesting heap segment b4fe0000
Failed to retrieve segments for gc heap
Unable to determine bounds of gc heap

我去,这个 dump 的栈被破坏了,可能是 cpu 爆高导致的,也有可能是抓的不好,这下太折磨了,得,只能用 kb 到非托管栈上找方法参数。

0:062:x86> kb# ChildEBP RetAddr      Args to Child              
00 3867ebfc 6b440484     cd0a25a8 124e2c7c 0efb330c mscorlib_ni!System.Collections.Generic.ObjectEqualityComparer`1[System.__Canon].Equals(System.__Canon, System.__Canon)$##6003913+0x1c
01 3867ec18 24bbc3c5     cd0a25a8 132b35e4 132b35cc mscorlib_ni!System.Collections.Generic.List`1[System.__Canon].Contains(System.__Canon)$##600398F+0x54
WARNING: Frame IP not in any known module. Following frames may be wrong.
02 3867ec98 24bbba00     0e3aead8 8412256c 3867ecc0 0x24bbc3c5
03 3867ecb8 05b5d487     0a3d6f00 3867f170 5381fbca 0x24bbba00
04 3867ecec 6092da13     0a3d6e48 00000000 132a20c0 0x5b5d487
05 3867ed04 5ffdd1cd     124ca1a8 80208dfc 80208dfc System_Web_ni![COLD] System.Web.UI.WebControls.Button.OnClick(System.EventArgs)$##60029E3+0xb
...

接下来我们 !do 一下 132b35cc 地址,看看是什么 list。

0:062:x86> !do 132b35cc
Name:        System.Collections.Generic.List`1[[xxx.Model.me_zyblbr, xxx]]
MethodTable: 29f36c8c
EEClass:     6b0aedc4
Size:        24(0x18) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:MT    Field   Offset                 Type VT     Attr    Value Name
6b4aea10  4001871        4     System.__Canon[]  0 instance 8e8054e0 _items
6b513c04  4001872        c         System.Int32  1 instance   233139 _size
6b513c04  4001873       10         System.Int32  1 instance   233139 _version
6b512104  4001874        8        System.Object  0 instance 00000000 _syncRoot
6b4aea10  4001875        4     System.__Canon[]  0   static  <no information>

用输出中可以看到,这个 list=23w 条记录,它正在 list.Contains 处,有了这些信息,接下来就可以把源码导出来,简化后的代码如下:

public IList<xxx> getBljl(string as_search, string as_ztbz){IList<me_zyblbr> list = new List<me_zyblbr>();using (CDataBase cDataBase = new CDataBase("xxx")){var text = "select xxxx  from xxx";OracleDataReader oracleDataReader = cDataBase.SetReader(text);while (oracleDataReader.Read()){if (!list.Contains(me_zyblbr)){list.Insert(0, me_zyblbr);}}oracleDataReader.Close();return list;}return list;}

眼尖的朋友肯定能注意到,在数据量大的情况下,这里的 list.Insert(0, me_zyblbr); 有大问题,毕竟 list.Insert 的复杂度是 O(N),针对 23w 来说总的时间复杂度就是:

n(n-1)/2 = 23w(23w-1)/2 = 26,450,000,000 = 264亿

然后就是 3个这样的线程就一起把cpu给抬起来了。

4. 到底是什么sql语句导致

虽然问题根已找到,但朋友最关心的是这位医生到底输入了什么导致 sql 查询了如此大的数据, 不知道医生要扣钱还是他们要向上面有个交代😂😂😂, 由于堆,栈都 被损坏了,找起来还是很麻烦的,我用了 sos 中的 !lno, !dumpheap 都是报错,彻底趴窝了,最后想了下 sosex 中也有一个 !mdso 命令,终于一路坎坷的找到了重要的 OracleParameter 参数。

0:062:x86> !mdso
Thread 62:
Location          Object            Type
------------------------------------------------------------
EDI:      132b35cc  System.Collections.Generic.List`1[[xxx.me_zyblbr, xxx]]
3867ec08  124e2c7c  System.Collections.Generic.ObjectEqualityComparer`1[[xxx.me_zyblbr, xxx]]
3867ec44  132b3a5c  Oracle.DataAccess.Client.OracleParameter0:062:x86> !mdt 132b3a5c
132b3a5c (Oracle.DataAccess.Client.OracleParameter)__identity:NULL (System.Object)m_pOpoPrmValCtx:4e691200 (System.UIntPtr)m_paramName:125fe6f0 (System.String) Length=5, String=":xxx"m_sourceColumn:NULL (System.String)m_sourceVersion:0x200 (System.Data.DataRowVersion)m_dbType:0x0 (System.Data.DbType)m_oraDbType:0x77 (NVarchar2) (Oracle.DataAccess.Client.OracleDbType)m_bOracleDbTypeExSet:false (System.Boolean)m_maxSize:0xffffffff (System.Int32)m_maxArrayBindSize:NULL (System.Int32[])m_nullable:false (System.Boolean)m_value:132b3af8 (System.String) Length=6, String="%高血压病%"

原来是医生模糊查询了一个 高血压病 导致的。。。

不过这里主要是想告诉大家的是,当由于内存遭到一定程度的破坏导致 sos 彻底趴窝也不要怕,可能还有其他的插件可以救我们于水火之中,多一个插件多一条路哈。

三:总结

总的来说,这次偶发的CPU爆高事故,犯的相对比较低级,对 List.Insert 的复杂度可能也不是很了解,也有可能是为了赶业务所欠的债吧,改发也相对简单,先用 add 送到 list,最后再统一按规则做一下重整排序。

END

工作中的你,是否已遇到 ... 

1. CPU爆高

2. 内存暴涨

3. 资源泄漏

4. 崩溃死锁

5. 程序呆滞

等紧急事件,全公司都指望着你能解决...  危难时刻才能展现你的技术价值,作为专注于.NET高级调试的技术博主,欢迎微信搜索: 一线码农聊技术,免费协助你分析Dump文件,希望我能将你的踩坑经验分享给更多的人。

e0839b447b5c5a1f601dd1c6c9ebfde4.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

执行CMD命令

可以执行多条命令&#xff0c;用“\r\n”分割 1 using System;2 using System.Diagnostics;3 4 namespace Tool5 {6 7 public class CMDHelper8 {9 public static string[] ExeCommand(string commandText) 10 { 11 12 Process p new Pr…

[iOS]应用内支付(内购)的个人开发过程及坑!

本文基于XcodeVersion 7.3 (7D175)版本&#xff0c;手机是iPhone 6&#xff0c;9.3系统。 一. 创建测试App 首先你需要登录 App的ItunesConnection&#xff0c;你会看到如下界面 简单的介绍一下这几个选项 1.我的App主要用于管理自己的App应用&#xff0c;例如编辑资料&…

Android之Intent 序列化反序列化

我们做截屏功能的时候&#xff0c;因为有2个进程&#xff0c;本来是把intent和MediaProjection放到Application里面&#xff0c;但是由于跨进程了&#xff0c;所以数据拿不到&#xff0c;就采用了Parcel 序列化出错,未找到出错的原因,找其它的解决方法: 查看Intent 的源代码, 发…

农商银行招聘计算机人员考什么,农商银行招聘考试题都考什么?

整理了农商农商一、行政职业能力测试类农商银行行测考试题型主要以选择题形式出现。主要包括言语理解、数量关系、判断推理、资料分析、常识五大部分。二、英语类农商银行考试英语部分&#xff1a;一般银行英语考试内容包括英语词汇与语法、英汉互译、改错、完型填空和阅读理解…

一步步学习微软InfoPath2010和SP2010--第八章节--使用InfoPath表单Web部件

本章中&#xff0c;你将学习到&#xff1a; 1. 配置Web部件设置 2. 创建Web部件连接 3. 创建表单参数 4. 使用其他浏览器表单参数 你可以使用InfoPath表单Web部件&#xff08;Microsoft SharePoint2010新引入的&#xff09;在SharePoint企业版或Microsoft…

讲一讲应用服务的新鲜事儿

微软中国MSDN 点击上方蓝字关注我们为了新功能的发布&#xff0c;以及 Linux 和 Windows 的改进&#xff0c;Azure App Service 团队付出了非常多的努力。很开心的是&#xff0c;我们看到了 Windows Containers 的正式版本&#xff0c;并可应用于 App Service 环境 v3 上。此外…

运维自动化之基于python语言的文字界面的运维管理软件

之前开发了phpmysqlshell运维监控系统&#xff0c;监控起来很方便&#xff0c;但在运维管理方便还是不能实现&#xff0c;所以最近打算使用python语言编写一套的运维管理系统&#xff0c;可以使用单台或多台机器同时管理与部署等功能&#xff0c;实现类似func、triaquae等管理软…

Android之4.0新特性

Android 4.0 平台 API等级:14 Android 4.0 是一次重要的平台发布版,为用户和应用程序开发者增加了大量的新特性。在下面我们将讨论的所有新特性和API中,因为它将 Android 3.x 版本中广泛使用的API和全息图像主题带给了小屏幕设备,因此我们说 Android 4.0 是一次重要的平…

iOS中的动画

2019独角兽企业重金招聘Python工程师标准>>> iOS中的动画 Core Animation Core Animation是一组非常强大的动画处理API,使用它能做出非常绚丽的动画效果,而且往往是事半功倍,使用它需要添加QuartzCore .framework和引入对应的框架<QuartzCore/QuartzCore.h>…

Debian7 apt源设置

刚装完系统时是没有 apt-spy 的&#xff0c;这时候我们可以暂时先找个可用的源代替&#xff0c;如&#xff08;写在 /etc/apt/sources.list 中&#xff09;&#xff1a; deb http://http.us.debian.org/debian/ stable main 执行以下命令更新软件包列表&#xff1a; apt-get up…

Android之6.0上的重要变化(一)

伴随着众多新特性和新功能,Android6.0(API level 23)在系统和API上都有着诸多的改变。本文着重介绍几个关键变化,以帮助你理解这些改变对你的APP产生的影响。 一、运行时权限检查(Runtime Permisssions) 此次发布引入了一个新的权限管理模型,使得用户能够在运行时控…

全世界70亿人同时起跳,地球会天崩地裂?答案可能让你难以置信

全世界只有3.14 % 的人关注了爆炸吧知识地球表示微微一笑不得不说&#xff0c;模友们的脑袋里总是充满了奇思妙想&#xff0c;比如超模君最近就收到了这么个问题&#xff1a;首先&#xff0c;这问题真就属于一看很有趣&#xff0c;细想全是BUG的那种。且不说怎么让70亿人同时聚…

计算机应用基础0006 18春在线作业1,《计算机应用基础0006》16春在线作业2

《计算机应用基础0006》16春在线作业2一、单选题(共 50 道试题&#xff0c;共 100 分。)1. 在Excel 2010的主界面中&#xff0c;不包含的选项卡是__B__&#xff1a; A. 公式B. 函数C. 插入D. 开始2. 以下属于无线接入互联网的是__D__&#xff1a; A. GPRS/CDMA B. WLAN C. 3G D…

2021.NET Conf China上的GraphQL

今天给大家分享.NET中的GraphQL&#xff0c;半个小时&#xff0c;没有把所有的代码敲出来&#xff0c;高估了自己的写码速度&#xff0c;所以通过这个文章分享出来。1、核心PPT2、主要代码using Conf2021GraphQL; using Conf2021GraphQL.Models; using Microsoft.EntityFramewo…

MyISAM和InnoDB的区别

mysql的存储引擎包括&#xff1a;MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDBCluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等&#xff0c;其中InnoDB和BDB提供事务安全表&#xff0c;其他存储引擎都是非事务安全表。 最常使用的2种存储引擎:  1.Myisam是Mysql的默认存…

JavaScript中“javascript:void(0) ”是什么意思

来源&#xff1a; <a href"javascript:test();void(0);">here</a> 此处&#xff1a;Javascript中void是一个操作符&#xff0c;该操作符指定要计算一个表达式但是不返回值。 void 操作符用法格式如下&#xff1a;1. javascript:void (expression)2. java…

Android之6.0上的重要变化(二)

十、Android KeyStore变化 此版本上Android Keystore provider不再支持DSA,仍旧支持ECDSA。 锁屏密码在(如用户或设备管理器)禁用或重置的情况下,不需要加密部分将不再被删除,而加密部分则会被删除。 十一、Wi-Fi和网络变化(Wi-Fi and Networking Changes) 此版本…

Oracle常用语句

一、导出有条件数据: exp zh/mmsignon tables(tablename1) filed:\aa.dmp query\"where IDC8ECD78D123C42AEA64910C30325CEA7\" 二、修改字符集&#xff1a; a.查看字符集 select * from v$nls_parameters b.客户端:cmd下运行set NLS_LANGSIMPLIFIED CHINESE_CHINA.Z…