昨天服务器的CPU突然100%,此服务已经运行几年了,都平安无事。既然问题出现当然要找出这个遗留多年的小概率问题。出现cpu 100% 一般就是哪里出现了无法跳出的死循环。

  1、获取进程的内存信息

  服务器使用的window server 直接右键创建转储文件即可。这个直接点点的方式是使用window server最方便的地方(^_^)。

  2、加载内存文件信息

  将文件复制本地,直接拖拽到windbg中。(windbg直接在window 应用商店下载即可)

  

  3、获取进程内耗时线程

  在0:000 输入框中输入!runaway 敲回车,获取线程占用cpu时间

  

  

  4、获取线程的栈信息

  从cpu的线程占用时间来看,线程64,89,96,95,90占用的时间最长,可以初步断定问题就出现在这几个线程中。输入:~64s进入该线程(64代表的是线程id)

  

  进入该线程后就可以加载线程的栈信息了,在命令框中输入!CLRStack 。如果出现图示信息说明需要单独加载SOS.dll 文件。使用everything软件全局搜索该dll文件位置,然后在输入框中:.load 全路径\SOS.dll。加载完成再次输入:!CLRStack 就可以正常显示栈信息了。

  

  5、问题定位

  从栈信息来看,线程一直停留在:System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)这个方法里面,调用这个方法的类是:Aop.Api.Parser.AopJsonParser,这个类是支付宝官方sdk中的。先看FindEntry这个方法干了啥。直接官网查看源码:

  

private int FindEntry(TKey key) {
if( key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
} if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= ; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
}
return -;
}

  从源码来就是判断key是否存在,看来就是死循环for里面了。再来看这个dictionary是用来干啥了的,反编译Aop dll文件

private static Dictionary<string, AopAttribute> GetAopAttributes(Type type)
{
Dictionary<string, AopAttribute> dictionary = null;
if (!AopJsonParser<T>.attrs.TryGetValue(type.FullName, out dictionary) || (dictionary == null))
{
dictionary = new Dictionary<string, AopAttribute>();
private static readonly Dictionary<string, Dictionary<string, AopAttribute>> attrs;

  从源码可以看见定义了一个静态Dictionary attrs变量,既然是静态变量,会出现多线程竞争问题。官网也明确说明Dictionary 是非线程安全的,如果多线程读写需要自己去写程序保证线程安全或者使用ConcurrentDictionary。

  6、问题

  问题的根本原因是多线程多写非线程安全Dictionary,导致在FindEntry方法死循环。

  

最新文章

  1. jquery toastr弹窗的代码和使用
  2. node 异步编程
  3. CSS中兼容的一面-----Hack
  4. Linux网卡的相关配置总结
  5. QUICK START GUIDE
  6. Linux常用指令---tail | head(查看文件)
  7. 【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期
  8. Java中的native方法
  9. Spring-----代码中使用注入的Properties配置属性
  10. @Transactional注解详解
  11. CodeForces 626C Block Towers
  12. C#全局鼠标键盘Hook
  13. dubbo框架初步学习
  14. abaqus python库变强变大233333333333333
  15. H5获取原生传过来的值
  16. VMvare虚拟机如何删除安装的ubuntu操作系统
  17. (转)EOS中账户、钱包和密钥的关系
  18. LeetCode67.二进制求和
  19. java设计模式之动态代理的概述和实现
  20. centos 安装MySQL全过程

热门文章

  1. MATLAB——神经网络train函数
  2. Django ORM相关
  3. 【Codeforces 848C】Goodbye Souvenir
  4. Linux命令——df/du/time
  5. java算法----排序----(6)希尔排序(最小增量排序)
  6. Python基础(dict 和 set) 字典和set
  7. NOI Day2线上同步赛崩盘记
  8. Luogu P3388 【模板】割点(割顶)
  9. Linux Shell完成Qt程序的自动部署
  10. 记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)