生产环境服务CPU高问题分析

问题描述:

现网个别时候会出现CPU突然飙高的现象,飙高后不能恢复正常。

分析过程:

CPU飙高后抓dump,最好本机看,其它机器看dump可能需要下载服务运行机器的sos,clr

?
?

0:000> !threadpool

The version of SOS does not match the version of CLR you are debugging.??Please

load the matching version of SOS for the version of CLR you are debugging.

CLR Version: 4.0.30319.276

SOS Version: 4.0.30319.17929

CPU utilization: 100%

Worker Thread: Total: 54 Running: 54 Idle: 0 MaxLimit: 32767 MinLimit: 8

Work Request in Queue: 0

--------------------------------------

Number of Timers: 3

--------------------------------------

Completion Port Thread:Total: 10 Free: 10 MaxFree: 16 CurrentLimit: 8 MaxLimit: 1000 MinLimit: 8

CPU确实高,54个线程都在跑着。

接着看线程都在干什么

0:000> ~*e!clrstack

OS Thread Id: 0x3278 (57)

Child SP?????????IP???????????????Call Site

000000000c72cea8 0000000077ef047a [RedirectedThreadFrame: 000000000c72cea8]

000000000c72cf40 000006448056c07e?********************.

SecurityQuota.ConcurrentLinkedQueue`1[[System.__Canon, mscorlib]].TryDequeue(System.__Canon ByRef)

000000000c72cff0 00000644805999e8?********************.SecurityQuota.SecurityFeatureDigest.GetIncrementalDigest(********************)

……

?
?

有50个线程在做该操作,review该处代码

为了防止本地代码和服务器不一致,直接反编译的服务器的代码,GetIncrementalDigest方法如下

public class SecurityFeatureDigest : ISecurityFeatureDigest

{

????// Fields

????private static Database _data = DatabaseManager.GetDatabase("SQSDB");

????private static readonly ITracing _tracer = TracingManager.GetTracing(typeof(SecurityFeatureDigest));

????private static ConcurrentLinkedQueue<List<FeatureDigest>> queue =

new ConcurrentLinkedQueue<List<FeatureDigest>>(new List<FeatureDigest>());?????(2)

????private static readonly string[] SetFeatureDigestParameter = new string[] { "@digest", "@operation", "@sample", "@stamp" };

?
?

????// 略…

?
?

????public void GetIncrementalDigest(RpcServerContext context)

????{

????????DateTime args = context.GetArgs<DateTime>();

????????List<FeatureDigest> results = new List<FeatureDigest>();

????????List<FeatureDigest> result = null;

????????while (true)

????????{

????????????if (queue.TryDequeue(out result))??????(1)

????????????{

????????????????List<FeatureDigest> list3 = new List<FeatureDigest>();

????????????????list3.AddRange(result);

????????????????queue.Enqueue(result);

????????????????foreach (FeatureDigest digest in list3)

????????????????{

????????????????????if (digest.Version > args)

????????????????????{

????????????????????????digest.Sample = string.Empty;

????????????????????????results.Add(digest);

????????????????????}

????????????????}

????????????????context.Return<List<FeatureDigest>>(results);

????????????????return;

????????????}

????????}

????}

?
?

????// 略…

?
?

}

从抓的dump看,极有可能是死循环了。通过以上代码看到,如果(1)处的返回为false的话,则改段代码会陷入死循环。接着看下什么情况下返回false。

public class ConcurrentLinkedQueue<T>

{

????// Fields

????private Node<T, T> _head;

????private Node<T, T> _tail;

?
?

????// 略…

???
?

????public bool TryDequeue(out T result)

????{

????????while (true)

????????{

????????????Node<T, T> comparand = this._head;

????????????Node<T, T> node2 = this._tail;

????????????Node<T, T> next = comparand.Next;

????????????if (comparand == this._head)

????????????{

????????????????if (next == null)???????(3)

????????????????{

????????????????????result = default(T);

????????????????????return false;

????????????????}

????????????????if (comparand == node2)

????????????????{

????????????????????Interlocked.CompareExchange<Node<T, T>>(ref this._tail, next, node2);

????????????????}

????????????????else

????????????????{

????????????????????result = next.Item;

????????????????????if (Interlocked.CompareExchange<Node<T, T>>(ref this._head, next, comparand) == comparand)

????????????????????{

????????????????????????break;

????????????????????}

????????????????}

????????????}

????????}

????????return true;

????}

(3)处可以看出,如果head的next为null的话,则返回false。为了确认分析是否正确,看下此处的值是不是null

0:000> !dumpheap -stat

Statistics:

??????????????MT????Count????TotalSize Class Name

000006448054b2d0????????1???????????32?********************.SecurityQuota.ConcurrentLinkedQueue`1

[[System.Collections.Generic.List`1[[********************.FeatureDigest, IICSecurityLibrary]], mscorlib]]

0:000> !dumpheap – -mt 000006448054b2d0???

------------------------------

Heap 6

?????????Address???????????????MT?????Size

00000001404836f0?000006448054b2d0???????32????

total 0 objects

Statistics:

??????????????MT????Count????TotalSize Class Name

000006448054b2d0????????1???????????32?********************.SecurityQuota.ConcurrentLinkedQueue`1

[[System.Collections.Generic.List`1[[********************.FeatureDigest,?*****]], mscorlib]]

Total 1 objects

0:000> !do 00000001404836f0

Name:????????********************.SecurityQuota.ConcurrentLinkedQueue`1[[System.Collections.Generic.List`1

[[********************.FeatureDigest,?*****]], mscorlib]]

MethodTable: 000006448054b2d0

EEClass:?????0000064480557a90

Size:????????32(0x20) bytes

File:????????********************\SecurityQuotaService.exe

Fields:

??????????????MT????Field???Offset?????????????????Type VT?????Attr????????????Value Name

000006448054b4d0??4000001????????8 ...Canon, mscorlib]]??0 instance?00000000c3135ec8?_head

000006448054b4d0??4000002???????10 ...Canon, mscorlib]]??0 instance?00000000c3135ec8?_tail

0:000> !do 00000000c3135ec8

Name:????????********************.SecurityQuota.ConcurrentLinkedQueue`1+Node`1[[System.Collections.Generic.List`1[[********************.

FeatureDigest,?*****]], mscorlib],[System.Collections.Generic.List`1[[********************.FeatureDigest,?*****]], mscorlib]]

MethodTable: 000006448054b7f8

EEClass:?????00000644805580b8

Size:????????32(0x20) bytes

File:????????********************\SecurityQuotaService.exe

Fields:

??????????????MT????Field???Offset?????????????????Type VT?????Attr????????????Value Name

00000644784c6040??4000003????????8???????System.__Canon??0 instance 00000001404836a8 Item

000006448054b4d0??4000004???????10 ...Canon, mscorlib]]??0 instance?0000000000000000?Next

发现Next为null

?
?

问题结论:

由于一些异常逻辑导致程序死循环,此处代码也有问题,对异常逻辑处理不够。

?
?

?

作者:No.40

Blog:http://www.cnblogs.com/no40

?

时间: 2024-10-10 14:50:03

生产环境服务CPU高问题分析的相关文章

生产环境如何快速跟踪、分析、定位问题-Java

我相信做技术的都会遇到过这样的问题,生产环境服务遇到宕机的情况下如何去分析问题?比如说JVM内存爆掉.CPU持续高位运行.线程被夯住或线程deadlocks,面对这样的问题,如何在生产环境第一时间跟踪分析与定位问题很关键.下来让我们看看通过如下步骤在第一时间分析问题. CPU占用较高场景 收集当前CPU占用较高的线程信息,执行如下命令: top -H -p PID -b -d 1 -n 1 > top.log或top -H -p PID 结果如下: 上图显示的都是某一个进程内的线程信息,找到cp

构建生产环境可用的高可用kubernetes集群

kubernetes集群三步安装 构建生产环境可用的高可用kubernetes集群 | sealos项目地址 特性 [x] 支持任意节点的etcd集群自动构建,且etcd集群使用安全证书,通过static pod方式启动,这样可以通过监控pod来监控etcd集群健康状态 [x] 支持多master节点,允许任意一台master宕机集群功能不受影响 [x] calico使用etcd集群,配置安全证书,网络管控数据无单点故障 [x] 包含dashboard, heapster coreDNS add

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

K8S环境中实践高可靠的配置和技巧都有哪些? 磁盘类型及大小 磁盘类型: 推荐使用ssd 磁盘 对于worker节点,创建集群时推荐使用挂载数据盘.这个盘是专门给/var/lib/docker 存放本地镜像.可以避免后续因镜像太多而造成磁盘根目录容量不够的情况.在运行一段时间后,本地会存在很多无用的镜像.比较快捷的方式就是,先下线这台机器,重新构建这个磁盘,然后再上线. 磁盘大小: kubernetes节点需要的磁盘空间也不小,Docker镜像.系统日志.应用日志都保存在磁盘上.创建kubern

MYSQL数据库服务CPU高问题分析与优化

MySQL服务性能监控分析与优化是永恒的主题,做为性能测试人员有时也要站在DBA角度出发进行适当分析与优化,这也是性能测试人员能长期生存发展之路.而资源的使用监控分析才是性能故障分析的根本首要任务.在数据库服务器内部,如果执行的操作会严重受到内存.CPU或磁盘吞吐量中任何一个的影响,则可以将它视为瓶颈. 因此理解服务器如何运行,资源损耗在哪些方面对问题进行故障诊断是非常有价值有意义的活动,具体案例如下. 这些监控分析优化方法等细节我们在品课学院性能实战课堂中都会以实战方式进行实操性测试监控分析实

高规格虚机 sys cpu高现场分析工具箱

导言 线上运行环境有时候会遇到cpu 飙升的场景,一般来讲对于多核的虚机,一个常见猝发场景就是高并发导致,核多并发高时,syscall会在锁这块 sys 消耗高,当然只有猜测不行,下面就列出了几个常见捉鬼工具 ,后半部分会拿一个示例. 工具箱 1.nmon promes 分析 尤其是promes ,比较推荐用起来,提供比较立体的系统级别监控 2.perf 分析 perf top -a -G perf top -a -e cs -G perf record -g -p 14778 -e cycle

Rancher 2.x 生产环境HA(高可用)部署

Rancher官方中文文档:https://www.rancher.cn/docs/rancher/v2.x/cn/overview/ 本次实验,为Ranche七层负载均衡Helm HA部署 一.环境准备 1.服务器配置 服务器使用腾讯云的虚拟机具体配置如下: 主机名称 系统版本 内网ip 公网ip 配 置 master1 CentOS 7.6 172.27.100.101 xxx 4C 16G master2 CentOS 7.6 172.27.100.101 xxx 4C 16G maste

生产环境的redis高可用集群搭建

这里只是总结一下安装步骤 如果要了解redis集群高可用的原理,推荐仔细看一遍配置文件示例http://download.redis.io/redis-stable/redis.conf,源码包里也有,里面的注释都是干货,看完会非常有帮助. 1.安装 wget http://download.redis.io/releases/redis-2.8.18.tar.gz tar xf redis-2.8.18.tar.gz cd redis-2.8.18.tar.gz make mkdir /usr

生产环境下mycat高可用方案mycat+keepalive(1)

#主master配置如下 cat  /etc/keepalived/keepalived.conf global_defs { notification_email { [email protected] } #notification_email_from [email protected] #smtp_server 10.168.0.48 #smtp_connect_timeout 10 router_id nginx } vrrp_script chk_haproxy { script "

生产环境服务器变慢,诊断思路和性能评估

生产环境服务器变慢,诊断思路和性能评估 整机:top 代码 public class JavaDemo2 { public static void main(String[] args) { while (true){ System.out.println(new java.util.Random().nextInt(77778888)); } } } top命令查看 [[email protected] ~]# top top - 11:28:50 up 7 min, 2 users, loa