记一次某网站生产环境CPU忽高忽低故障解决过程
感谢
感谢【一级码农】 的帮助,之前也读了大佬的好多文章,一直在学习中,也没有实际操作过。
这次的过程也是在大佬的指点下完成的。
现象描述
从周六上午开始,陆续收到服务器CPU高的报警短信,到下午已经累计三十多条报警了,看来确实得分析一下原因了。
打开云监控,与实际情况一致,CPU居高不下

通过进程,很快锁定是哪个应用,是一个car系统造成的

car系统的版本是.net 4.0

分析过程
通过以下命令,抓包,命令解释,当CPU超过50%时,持续三秒,抓两个包。进程ID是6100。进程ID在任务管理器中可以看到。
procdump -ma -c 50 -s 3 -n 2 6100
遇到如下错误

出现以上错误是因为没有用管理员运行CMD,重新用管理员打开即可。

很快抓包完成。从服务器down到本地。
# 加载sos和clr文件
0:016> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
0:016> .load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
0:062> !runaway
User Mode Time
Thread Time
16:dc4 0 days 0:13:12.593
15:2be4 0 days 0:13:06.390
17:2404 0 days 0:13:06.328
18:bb4 0 days 0:12:45.953
39:3294 0 days 0:04:10.500
44:320 0 days 0:04:07.281
38:3b24 0 days 0:04:06.156
43:176c 0 days 0:04:00.218
46:1118 0 days 0:03:55.359
50:2a3c 0 days 0:03:54.921
40:1aac 0 days 0:03:50.531
51:2fb4 0 days 0:03:49.421
47:2508 0 days 0:03:48.718
!runaway发现前几个线程时间很长,那么他们在干什么呢?
切到 16 号线程~16s
0:016> !clrstack
PDB symbol for clr.dll not loaded
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
2) the file mscordacwks.dll that matches your version of clr.dll is
in the version directory or on the symbol path
3) or, if you are debugging a dump file, verify that the file
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
4) you are debugging on supported cross platform architecture as
the dump file. For example, an ARM dump file must be debugged
on an X86 or an ARM machine; an AMD64 dump file must be
debugged on an AMD64 machine.
You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll. .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
上面不是提示sos clr文件不对吗,在服务器上分析是没有报这个错的,所以我从服务器上弄了两个回来
.load D:\soft\WinDbg+procdump\procdump\car\sos.dll
.load D:\soft\WinDbg+procdump\procdump\car\clr.dll
0:018> .load D:\soft\WinDbg+procdump\procdump\car\sos.dll
0:018> .load D:\soft\WinDbg+procdump\procdump\car\clr.dll
0:018> !clrstack
PDB symbol for clr.dll not loaded
OS Thread Id: 0xbb4 (18)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
Failed to start stack walk: 80070057
OK,现在不提示配置问题了。继续分析
0:016> !clrstack
OS Thread Id: 0xdc4 (16)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
Failed to start stack walk: 80070057
0:016> ~15s
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00000000 edi=0000053c
eip=76f2c0bc esp=1af3fbfc ebp=1af3fc6c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
ntdll!NtWaitForSingleObject+0xc:
76f2c0bc c20c00 ret 0Ch
前四个线程,都提示not a managed thread

请教了一下【一级码农】大佬,这个方向可能是错误的。那我们就只能换一个方向。
这里大佬已经告诉我是拖管线程的问题,如果是我们首次分析,可能还需要先判断是拖管还是非拖管的问题。这个后面再慢慢消化加上去。
我们这里走一个捷径,直接查拖管线程,有时候你也可以假装碰碰运气,说不定就能找到原因了呢。
~*e !clrstack 发现触发了GC回收


!dumpstack 显示当前调用栈上的所有托管对象的信息,

发现这个Volcker.Autotrader.ProductPropertieData.GetAll()方法出现多次,明显有多个线程卡在这里了。那这个方法是干啥的呢,
查看一下源码就知道了。
当然,如果有时候你手里没有源码,或者服务器运行的和本地代码差异比较大,那就导出源代码
0:053> !ip2md 1c15f4bd
MethodDesc: 1b9ec174
Method Name: Volcker.Autotrader.ProductPropertieData.GetAll()
Class: 1bd668a4
MethodTable: 1b9ec19c
mdToken: 06000088
Module: 1b9ebbd4
IsJitted: yes
CodeAddr: 1c15f420
Transparency: Critical
0:053> !savemodule 1b9ebbd4 D:\dumps\car-cpu\GetAll.dll
3 sections in file
section 0 - VA=2000, VASize=1714c, FileAddr=200, FileSize=17200
section 1 - VA=1a000, VASize=3e8, FileAddr=17400, FileSize=400
section 2 - VA=1c000, VASize=c, FileAddr=17800, FileSize=200
需要提前创建好目录 D:\dumps\car-cpu,找到上面的方法

这一行代码是干啥的呢,解释一下,其实是个通用的将数据库表转换为实体类的方法。
/// <summary>
/// 根据IDataReader对属性进行赋值
/// </summary>
/// <param name="reader">
new public void LoadDataReader(IDataReader reader)
{
LoadDataReader(MethodBase.GetCurrentMethod(), this, reader);
}
/// <summary>
/// 根据DataReader为对象属性赋值
/// </summary>
/// <param name="method">所属类MethodBase对象
/// <param name="obj">
/// <param name="reader">设置其属性 (Property) 值的对象
/// <returns></returns>
virtual public void LoadDataReader(MethodBase method, Object obj,IDataReader reader)
{
Hashtable cols = new Hashtable();
for (var i = 0; i < reader.FieldCount; i++)
{
cols.Add(reader.GetName(i).ToLower(), reader.GetValue(i)); //装入数据到hashtable中
}
Hashtable h = GetFieldProperties(method, FieldType.DBField); //获取属性的Hasttable
foreach (var o in h.Keys)
{
PropertyInfo p = (PropertyInfo)h[o];
Object v = null;
if (cols.Contains(o))
{
v = cols[o];
}
if (v != null)
{
SetPropertieValue(ref obj, ref p, ref v);
}
}
}
这里用了一个反射,通过上面的分析得到,问题出在这一行
Hashtable h = GetFieldProperties(method, FieldType.DBField); //获取属性的Hasttable
可能是这个类或者方法的属性太多吧,或者其他原因造成的。
可能一开始写这个反射方法用法没有错,但是防不住后面有人在类中或者方法中加了其他的东东,造成反射有问题了。
我以前也写过类似的方法,没有这个智能,但也从来没出过问题。
有时候,太智能了也没有啥必要,
最简单的代码效率最高,搞这么复杂有必要吗?
不说这个了,解决问题先
由于代码历史太悠久,相关细节完全不清楚,所以也不敢改动太大
目前的办法就是加缓存,这个其实是个字典表,理论上变化不会很大,所以加了24小时的缓存,24小时请求一次。
改一下代码,更新一下看看。
效果很明显啊,再观察几天看看。

总结
上面的分析过程基本上比较详细了,但有些步骤可能没有啥逻辑,原因就是靠经验,或者运气。经历的越多,可能猜一下就大概知道原因在哪
再次感谢【一线码农】的帮助,下面是大佬的总结

参考文章
一线码农的github
教你配置windows上的windbg,linux上的lldb,打入clr内部这一篇就够了
记一次某网站生产环境CPU忽高忽低故障解决过程的更多相关文章
- 生产环境CPU过高问题定位
问题描述: 生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 解决过程: 1.根据top命令,发现 ...
- 生产环境JAVA进程高CPU占用故障排查
问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...
- K8S生产环境中实践高可靠的配置和技巧都有哪些?
K8S环境中实践高可靠的配置和技巧都有哪些? 磁盘类型及大小 磁盘类型: 推荐使用ssd 磁盘 对于worker节点,创建集群时推荐使用挂载数据盘.这个盘是专门给/var/lib/docker 存放本 ...
- linux安装Django 以及 生产环境部署实现高并发
1.首先安装python Python编译安装 主要介绍linux环境下安装 cd /usr/local/src //进入安装目录 wget https://www.python.org/ ...
- 【转】生产环境:Nginx高可用方案
准备工作: 192.168.16.128 192.168.16.129 两条虚拟机.安装好 Nginx 安装Nginx 更新 yum 源文件: rpm -ivh http://nginx.org/pa ...
- 生产环境之Nginx高可用方案
准备工作: 192.168.16.128 192.168.16.129 两台虚拟机.安装好Nginx 安装Nginx 更新yum源文件: rpm -ivh http://nginx.org/packa ...
- 生产系统CPU飙高问题排查
现状 生产系统CPU占用过高,并且进行了报警 排查方法 执行top命令,查看是那个进程导致的,可以确定是pid为22168的java应用导致的 执行top -Hp命令,查看这个进程的那个线程导致cpu ...
- MySQL CPU 使用率高的原因和解决方法
用户在使用 MySQL 实例时,会遇到 CPU 使用率过高甚至达到 100% 的情况.本文将介绍造成该状况的常见原因以及解决方法,并通过 CPU 使用率为 100% 的典型场景,来分析引起该状况的原因 ...
- C# Winform程序CPU占用高的原因和解决方法
程序CPU占用高的可能原因: 1.存在死循环: 为什么死循环会导致CPU占用高呢? 虽然分时操作系统是采用时间片的机制对CPU的时间进行管理的,也就是说到了一定时间它会自动从一个进程切换到下 ...
随机推荐
- noip42
T1 朴素dp很好想,设 \(dp_{u,0/1}\) ,表示以 \(u\) 为根的子树,选/不选 \(u\) 所产生的最大贡献. 转移方程则有, \[dp_{u,0} = \prod_{v\in s ...
- linux中的分号&&和&,|和||说明与用法
在用linux命令时候,我们可以一行执行多条命令或者有条件的执行下一条命令,下面我们讲解一下linux命令分号&&和&,|和||的用法 在用linux命令时候,我们可以一行执行 ...
- CentOS7 yum方式安装MySQL5.7 + 远程连接
1 下载并安装MySQL官方的 Yum Repository [root@localhost ~]# wget -i -c http://dev.mysql.com/get/mysql57-commu ...
- 深入浅出Mybatis系列(六)---配置详解之typeAliases别名
本篇继续讲剩下的配置节点之一:typeAliases. typeAliases节点主要用来设置别名,其实这是挺好用的一个功能, 通过配置别名,我们不用再指定完整的包名,并且还能取别名. 例如: 我们在 ...
- 从eclipse转idea不适记录【持续更新】
使用eclipse和idea时,快捷键对比 从一些最扎心的开始: 关于print一类的打印输出:System.out.println()补全 idea中可以sout.souf.serr:分别对应out ...
- ProjectEuler 006题
题目: The sum of the squares of the first ten natural numbers is, 12 + 22 + ... + 102 = 385 The square ...
- Flink Data transformation(转换)
Flink Data transformation 算子学习 1.Source:数据源,Flink在流处理和批处理上的source大概有4类: 基于本地集合的source.基于文件的source.基于 ...
- SpringBoot博客开发之异常处理
异常处理: 背景: 最近在搭建属于自己的个人博客(码农小白的执念),自己搭建后端的时候首先考虑的是异常处理.个人也是一边学习一边做,难免有疏漏的地方,希望朋友们在不对的地方提醒下. 技术栈: spri ...
- sizeof关键字
sizeof关键字 sizeof不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型的大小,单位为字节 sizeof的返回值为size_t size_t类型在32位操作系统下是unsigne ...
- Microsoft Remote Desktop 通过 .rdp 文件登录
最近在淘宝上买了「市场洞察」子账号,说是子账号,其实是需要登录到他们的 Windows 服务器上才能用的.并且子账号也是 5-6 个人共用的,且不说远程服务器很老又有延迟,经常是我想添加一个监控店铺或 ...