感谢

感谢【一级码农】 的帮助,之前也读了大佬的好多文章,一直在学习中,也没有实际操作过。

这次的过程也是在大佬的指点下完成的。

现象描述

从周六上午开始,陆续收到服务器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忽高忽低故障解决过程的更多相关文章

  1. 生产环境CPU过高问题定位

    问题描述:       生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 解决过程: 1.根据top命令,发现 ...

  2. 生产环境JAVA进程高CPU占用故障排查

    问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...

  3. K8S生产环境中实践高可靠的配置和技巧都有哪些?

    K8S环境中实践高可靠的配置和技巧都有哪些? 磁盘类型及大小 磁盘类型: 推荐使用ssd 磁盘 对于worker节点,创建集群时推荐使用挂载数据盘.这个盘是专门给/var/lib/docker 存放本 ...

  4. linux安装Django 以及 生产环境部署实现高并发

    1.首先安装python Python编译安装 主要介绍linux环境下安装 cd  /usr/local/src     //进入安装目录 wget  https://www.python.org/ ...

  5. 【转】生产环境:Nginx高可用方案

    准备工作: 192.168.16.128 192.168.16.129 两条虚拟机.安装好 Nginx 安装Nginx 更新 yum 源文件: rpm -ivh http://nginx.org/pa ...

  6. 生产环境之Nginx高可用方案

    准备工作: 192.168.16.128 192.168.16.129 两台虚拟机.安装好Nginx 安装Nginx 更新yum源文件: rpm -ivh http://nginx.org/packa ...

  7. 生产系统CPU飙高问题排查

    现状 生产系统CPU占用过高,并且进行了报警 排查方法 执行top命令,查看是那个进程导致的,可以确定是pid为22168的java应用导致的 执行top -Hp命令,查看这个进程的那个线程导致cpu ...

  8. MySQL CPU 使用率高的原因和解决方法

    用户在使用 MySQL 实例时,会遇到 CPU 使用率过高甚至达到 100% 的情况.本文将介绍造成该状况的常见原因以及解决方法,并通过 CPU 使用率为 100% 的典型场景,来分析引起该状况的原因 ...

  9. C# Winform程序CPU占用高的原因和解决方法

    程序CPU占用高的可能原因: 1.存在死循环: 为什么死循环会导致CPU占用高呢?      虽然分时操作系统是采用时间片的机制对CPU的时间进行管理的,也就是说到了一定时间它会自动从一个进程切换到下 ...

随机推荐

  1. Anaconda安装和使用

    Anaconda anaconda (开源的Python包管理器) 编辑 讨论 上传视频 Anaconda指的是一个开源的Python发行版本,其包含了conda.Python等180多个科学包及其依 ...

  2. Dapps-是一个跨平台的应用服务商店

    简介 Dapps 是一个跨平台的应用商店,包含众多软件,基于docker dapps是什么? 它是一个应用程序商店,包含丰富的软件,因为基于docker,使你本机电脑有云开发的效果. 一键安装程序:多 ...

  3. 在ASP.NET Core调用WebService

    一.前言 现实生产中,有一些比较老的系统对外提供的接口都是WebService形式的,如果是使用.NET Framework创建的项目调用WebService非常方便,网上有很多代码示例,这里不在讲解 ...

  4. C#中调用c++的dll具体创建与调用步骤,亲测有效~ (待验证)

    使用的工具是VS2010哦~其他工具暂时还没试过 我新建的工程名是my21dll,所以会生成2个同名文件.接下来需要改动的只有画横线的部分 下面是my21dll.h里面的... 下面的1是自动生成的不 ...

  5. 【转】SpringCloud学习

    Spring Cloud Alibaba与Spring Boot.Spring Cloud之间不得不说的版本关系   这篇博文是临时增加出来的内容,主要是由于最近连载<Spring Cloud ...

  6. 详述 MySQL 中的行级锁、表级锁和页级锁

    转自:https://blog.csdn.net/qq_35246620/article/details/69943011 refer:cnblogs.com/f-ck-need-u/p/899547 ...

  7. Spring第一课:依赖注入DI(二)

    DI Dependency Injection ,依赖注入 is a :是一个,继承. has a:有一个,成员变量,依赖. class B { private A a;   //B类依赖A类 } 依 ...

  8. Alibaba cloud 3 安装docker

    最近因为公司买阿里服务器装的 Alibaba cloud Linux 系统,在部署环境的时候也是遇到各种坑,网上教程大多都是其他系统的,今天就来分享一下自己安装Docker的步骤,同时也是给自己记录一 ...

  9. Workflow Core + asp.net core 5.0 实现简单审批工作流

    我们知道企业业务系统到处都可以审批工作流的,但也很少有像OA系统一样复杂多级多条件的审批工作流需要设计,所以我们需要一个轻量级的容易上手的workflow框架,通过GitHub,我发现danielge ...

  10. webpack4学习之 babel

    webpack之前一知半解,这次有空就把最新的webpack4好好学习一下(2019-05-29 因为webpack的很多东西版本都在升级,网上博客很多都是老版本的,所以加个时间方便大家决定是否有必要 ...