记一次某网站生产环境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的时间进行管理的,也就是说到了一定时间它会自动从一个进程切换到下 ...
随机推荐
- Mysql 主从同步原理简析
在开始讲述原理的情况下,我们先来做个知识汇总,究竟什么是主从,为什么要搞主从,可以怎么实现主从,mysql主从同步的原理1.什么是主从其实主从这个概念非常简单主机就是我们平常主要用来读写的服务,我们称 ...
- Angular Module 共享模块使用 父模块使用多个子模块
Component.module.ts import {BrowserModule} from '@angular/platform-browser'; import {LocationStrat ...
- spring boot 的JPA项目
pom 文件 -------------------------------------------------------------------------- <dependencies&g ...
- mysql优化: 内存表和临时表
由于直接使用临时表来创建中间表,其速度不如人意,因而就有了把临时表建成内存表的想法.但内存表和临时表的区别且并不熟悉,需要查找资料了.一开始以为临时表是创建后存在,当连接断开时临时表就会被删除,即临时 ...
- 字节跳动基于Apache Hudi构建EB级数据湖实践
来自字节跳动的管梓越同学一篇关于Apache Hudi在字节跳动推荐系统中EB级数据量实践的分享. 接下来将分为场景需求.设计选型.功能支持.性能调优.未来展望五部分介绍Hudi在字节跳动推荐系统中的 ...
- 【C语言】第1章 程序设计与C语言
第1章 程序设计与C语言 程序:一组计算机能识别和执行的 指令. 计算机语言:人和计算机交流信息的.计算机和人都能识别的语言 C语言允许用两种注释方式: //:单行注释 可单独占一行 可出现在一行中其 ...
- T-SQL - 习题02_将数据表year|month|amount查询成year|m1|m2|m3|m4的样式
时间:2017-09-11 整理:byzqy 题目:有个年度统计表,结构如下: 怎么样把这个表,查询成这样一个结果: 这是在面试过程中遇到的一个关于数据库的题,没有一点思路,不知它考查到的知识点是什么 ...
- JDBC简介及JDBC编写步骤及常见API
JDBC : Java Database Connectivity,Java数据库连接.SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC. JDBC就像一座桥 ...
- vue-class和style样式绑定
前言 操作元素的 class 样式列表和 style 内联样式为数据绑定是前端开发中一个常见的需求,这些样式都属于元素的属性 attribute ,因此我们可以通过 v-bind 来动态绑定元素的样式 ...
- SpringBoot详解(一)——
https://www.cnblogs.com/lifullmoon/p/14957771.html https://www.cnblogs.com/lifullmoon/p/14957751.htm ...