一:背景

1. 讲故事

早就听说过有什么 网络边缘计算,这次还真给遇到了,有点意思,问了下 chatgpt 这是干嘛的 ?

网络边缘计算是一种计算模型,它将计算能力和数据存储位置从传统的集中式数据中心向网络边缘的用户设备、传感器和其他物联网设备移动。这种模型的目的是在接近数据生成源头的地方提供更快速的计算和数据处理能力,从而减少数据传输延迟并提高服务质量。网络边缘计算使得在设备本地进行数据处理和决策成为可能,同时也有助于减轻对中心数据中心的网络流量和负载。

看到.NET还有这样的应用场景还是挺欣慰的,接下来就来分析下这个dump到底是怎么回事?

二:WinDbg 分析

1. 为什么会卡死

不同程序的卡死有不同的分析方式,所以要先鉴别下程序的类型以及主线程的调用栈即可,参考如下:


0:000> !eeversion
5.0.721.25508
5.0.721.25508 @Commit: 556582d964cc21b82a88d7154e915076f6f9008e
Server mode with 64 gc heaps
SOS Version: 8.0.10.10501 retail build 0:000> k
# Child-SP RetAddr Call Site
00 0000ffff`e0dddac0 0000fffd`c194c30c libpthread_2_28!pthread_cond_wait+0x238
...
18 (Inline Function) --------`-------- libcoreclr!RunMain::$_0::operator()::{lambda(Param *)#1}::operator()+0x14c [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1536]
19 (Inline Function) --------`-------- libcoreclr!RunMain::$_0::operator()+0x188 [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1538]
1a 0000ffff`e0dde600 0000fffd`c153e860 libcoreclr!RunMain+0x298 [/__w/1/s/src/coreclr/src/vm/assembly.cpp @ 1538]
...
20 0000ffff`e0dded10 0000fffd`c1bf7800 libhostpolicy!corehost_main+0xc0 [/root/runtime/src/installer/corehost/cli/hostpolicy/hostpolicy.cpp @ 409]
21 (Inline Function) --------`-------- libhostfxr!execute_app+0x2c0 [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 146]
22 (Inline Function) --------`-------- libhostfxr!<unnamed-namespace>::read_config_and_execute+0x3b4 [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 520]
23 0000ffff`e0ddeeb0 0000fffd`c1bf6840 libhostfxr!fx_muxer_t::handle_exec_host_command+0x57c [/root/runtime/src/installer/corehost/cli/fxr/fx_muxer.cpp @ 1001]
24 0000ffff`e0ddf000 0000fffd`c1bf4090 libhostfxr!fx_muxer_t::execute+0x2ec
25 0000ffff`e0ddf130 0000aaad`c9e1d22c libhostfxr!hostfxr_main_startupinfo+0xa0 [/root/runtime/src/installer/corehost/cli/fxr/hostfxr.cpp @ 50]
26 0000ffff`e0ddf200 0000aaad`c9e1d468 dotnet!exe_start+0x36c [/root/runtime/src/installer/corehost/corehost.cpp @ 239]
27 0000ffff`e0ddf370 0000fffd`c1c63fe0 dotnet!main+0x90 [/root/runtime/src/installer/corehost/corehost.cpp @ 302]
28 0000ffff`e0ddf3b0 0000aaad`c9e13adc libc_2_28!_libc_start_main+0xe0
29 0000ffff`e0ddf4e0 00000000`00000000 dotnet!start+0x34

从卦中的指标来看,这是一个 Linux 上部署的 Web网站,既然是网站的卡死,那就要关注各个线程都在做什么。

2. 线程都在干嘛

以我多年的分析经验,绝大多数都是由于 线程饥饿 或者说 线程池耗尽 导致的,首先我们看下线程池的情况。


0:000> !t
ThreadCount: 365
UnstartedThread: 0
BackgroundThread: 354
PendingThread: 0
DeadThread: 10
Hosted Runtime: no
Lock
DBG ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 31eaf 0000AAADF267C600 2020020 Preemptive 0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn
...
423 363 36d30 0000FFDDB4000B20 1020220 Preemptive 0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker)
424 364 36d31 0000FFDDA8000B20 1020220 Preemptive 0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker)
425 365 36d32 0000FFDDAC000B20 1020220 Preemptive 0000000000000000:0000000000000000 0000aaadf26634b0 -00001 Ukn (Threadpool Worker) 0:000> !tp
Using the Portable thread pool. CPU utilization: 9%
Workers Total: 252
Workers Running: 236
Workers Idle: 13
Worker Min Limit: 64
Worker Max Limit: 32767 Completion Total: 0
Completion Free: 0
Completion MaxFree: 128
Completion Current Limit: 0
Completion Min Limit: 64
Completion Max Limit: 1000

从卦中看当前有 365 个托管线程,这个算多吗?对于64core 来说,这个线程其实算是正常,训练营里的朋友都知道,server版的gc仅gc线程就有 64*2=128 个,接下来再看一个指标就是当前是否存在任务积压? 可以使用 !ext tpq 命令,参考输出如下:


0:000> !ext tpq
global work item queue________________________________ local per thread work items_____________________________________

从卦中看当前没有任务积压,这就有点反经验了。

3. 真的不是线程饥饿吗

最后一招比较彻底,就是看各个线程栈都在做什么,可以使用 ~*e !clrstack 命令。

这不看不知道,一看吓一跳,有 193 个线程在 Task.Result 上等待,这玩意太经典了,然后从上面的调用栈 UIUpdateTimer_Elapsed 来看,貌似是一个定时器导致的,接下来我就好奇这代码是怎么写的?

分析上面的代码之后,我发现它是和 Linux Shell 窗口进行命令交互,不知道为何 Shell 没有响应导致代码在这里卡死。

4. 为什么线程池没有积压

相信有很多朋友对这个反经验的东西很好奇为什么请求没有积压在线程池,其实这个考验的是你对 PortableThreadPool 的底层了解,这里我就简单说一下吧。

  1. 在 ThreadPool 中有一个 GateThread 线程是专门给线程池动态注入线程的,参考代码如下:

private static class GateThread
{
private static void GateThreadStart()
{
while (true)
{
bool wasSignaledToWake = DelayEvent.WaitOne((int)delayHelper.GetNextDelay(tickCount)); WorkerThread.MaybeAddWorkingWorker(threadPoolInstance);
}
}
}
  1. 一旦有人调用了 Task.Result 代码,内部会主动唤醒 DelayEvent 事件,告诉 GateThread 赶紧通过 MaybeAddWorkingWorker 方法给我注入新的线程,参考代码如下:

private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken cancellationToken)
{
bool flag3 = ThreadPool.NotifyThreadBlocked(); }
internal static bool NotifyThreadBlocked()
{
if (UsePortableThreadPool)
{
return PortableThreadPool.ThreadPoolInstance.NotifyThreadBlocked();
}
return false;
}
public bool NotifyThreadBlocked()
{
GateThread.Wake(this);
}

上面这种主动唤醒的机制是 C# 版 PortableThreadPool 做的优化来缓解线程饥饿的,这里有一个重点就是它只能缓解,换句话说如果上游太猛了还是会有请求积压的,但为什么这里没有积压呢? 很显然上游不猛呗,那如何眼见为实呢? 这就需要看 timer 的周期数即可,到当前的线程栈上给扒出来。


0:417> !DumpObj /d 0000ffee380757f8
Name: System.Timers.Timer
MethodTable: 0000fffd4ab24030
EEClass: 0000fffd4ad6e140
Size: 88(0x58) bytes
File: /home/user/env/dotnet/shared/Microsoft.NETCore.App/5.0.7/System.ComponentModel.TypeConverter.dll
Fields:
MT Field Offset Type VT Attr Value Name
0000fffd4c947498 400001c 8 ...ponentModel.ISite 0 instance 0000000000000000 _site
0000000000000000 400001d 10 ....EventHandlerList 0 instance 0000000000000000 _events
0000fffd479195d8 400001b 98 System.Object 0 static 0000000000000000 s_eventDisposed
0000fffd47926f60 400000e 40 System.Double 1 instance 3000.000000 _interval
0000fffd4791fb10 400000f 48 System.Boolean 1 instance 1 _enabled
0000fffd4791fb10 4000010 49 System.Boolean 1 instance 0 _initializing
0000fffd4791fb10 4000011 4a System.Boolean 1 instance 0 _delayedEnable
0000fffd4ab241d8 4000012 18 ...apsedEventHandler 0 instance 0000ffee3807aae8 _onIntervalElapsed
0000fffd4791fb10 4000013 4b System.Boolean 1 instance 1 _autoReset
0000fffd4c944ea0 4000014 20 ...SynchronizeInvoke 0 instance 0000000000000000 _synchronizingObject
0000fffd4791fb10 4000015 4c System.Boolean 1 instance 0 _disposed
0000fffd49963e28 4000016 28 ...m.Threading.Timer 0 instance 0000ffee38098dc8 _timer
0000fffd48b90a30 4000017 30 ...ing.TimerCallback 0 instance 0000ffee3807aaa8 _callback
0000fffd479195d8 4000018 38 System.Object 0 instance 0000ffee38098db0 _cookie

从卦中看当前是 3s 为一个周期,这就能解释为什么线程池没有积压的底层原因了。

三:总结

这个卡死事故还是蛮好解决的,如果有一些经验直接用dotnet-counter也是能搞定的,重点在于这是一个 Linux的dump,同时又是 .NET上的一个很好玩的场景,故此分享出来。

记一次 .NET某网络边缘计算系统 卡死分析的更多相关文章

  1. 记一次 .NET 某药品仓储管理系统 卡死分析

    一:背景 1. 讲故事 这个月初,有位朋友wx上找到我,说他的api过一段时间后,就会出现只有请求,没有响应的情况,截图如下: 从朋友的描述中看样子程序是被什么东西卡住了,这种卡死的问题解决起来相对简 ...

  2. 记一次 .NET 某金融企业 WPF 程序卡死分析

    一:背景 1. 讲故事 前段时间遇到了一个难度比较高的 dump,经过几个小时的探索,终于给找出来了,在这里做一下整理,希望对大家有所帮助,对自己也是一个总结,好了,老规矩,上 WinDBG 说话. ...

  3. 记一次 .NET 某数控机床控制程序 卡死分析

    一:背景 1. 讲故事 前段时间有位朋友微信上找到我,说它的程序出现了卡死,让我帮忙看下是怎么回事? 说来也奇怪,那段时间求助卡死类的dump特别多,被迫训练了一下对这类问题的洞察力 ,再次声明一下, ...

  4. [转帖]记一次KUBERNETES/DOCKER网络排障

    记一次KUBERNETES/DOCKER网络排障 https://coolshell.cn/articles/18654.html 记得之前在一个公众号里面看过这个文章 讲的挺好的.. 物理机直接跑d ...

  5. VMware vRealize Network Insight 6.2 发布 - 网络和安全可视化分析

    发现.优化应用安全性和网络连接解决方案并对其进行故障排除 VMware vRealize Network Insight 可帮助您跨混合和多云环境构建经过优化且高度可用的安全网络基础架构.它提供了网络 ...

  6. Cacti 是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具

    Cacti 是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具. mysqlreport是mysql性能监测时最常用的工具,对了解mysql运行状态和配置调整都有很大 ...

  7. Android-蓝牙的网络共享与连接分析

    一.概述 本次分析是基于android7.0的源码,主要是介绍如何通过反射来打开蓝牙的网络共享以及互联网的连接. 二.蓝牙的网络共享 1. 网络共享部分源码分析 关于packages/apps/Set ...

  8. 开源网络抓包与分析框架学习-Packetbeat篇

    开源简介packbeat是一个开源的实时网络抓包与分析框架,内置了很多常见的协议捕获及解析,如HTTP.MySQL.Redis等.在实际使用中,通常和Elasticsearch以及kibana联合使用 ...

  9. 网络协议图形化分析工具EtherApe

    网络协议图形化分析工具EtherApe   在对网络数据分析的时候,渗透测试人员往往只关心数据流向以及协议类型,而不关心具体数据包的内容.因为这样可以快速找到网络的关键节点或者重要的协议类型. Kal ...

  10. # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#

    Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...

随机推荐

  1. [ABC345D] Tiling 位运算の极致运用

    [ABC345D] Tiling 原题解地址:Editorial by Kiri8128 神写法. 将 \(H \times W\) 的网格展开为 \(H \times (W + 1)\) 的序列, ...

  2. 《深度学习原理与Pytorch实战》(第二版)

    第1章 深度学习简介 深度学习--利用深度人工神经网络来进行自动分类.预测和学习的技术,深度学习=深度人工神经网络 超过三层的神经网络都可以叫做深度神经网络 人工神经网络的关键算法--反向传播算法 深 ...

  3. 01 elasticsearch学习笔记-环境安装

    docker-compose安装EFK git clone https://github.com/haimait/docker_compose_efk docker-compose up -d Flu ...

  4. 04. C语言数据使用方式

    [C语言简介] 计算机的运行由CPU指令控制,为了让计算机执行指定功能,需要将这些功能对应的指令数据集中存储在一起,制作为一个计算机文件,这个文件称为程序,CPU通过读取程序中的指令确定要执行的功能, ...

  5. cesium问题-关于不同时间模型亮度不一致问题

    项目中遇到发布的bim模型在当天不同时间的模型亮度发生变化,尤其是晚上的时候会出现模型很暗.尴了个尬,一度怀疑是自己眼睛有问题,连续几天出现同样的情况,想到可能是时间问题导致的模型亮度不同,于是测试了 ...

  6. UE4 C++调用C# DLL(DllExport方法)

    之前看见园子里一篇C++调用C#的文章,参考后拿UE试一下.刚开始尝试了C# dll > CLR C++ DLL > Native C++ DLL的做法, 原生环境下是可以的,但是到UE4 ...

  7. 简易的 Linux 流量实时监控工具 watch+ifstat

    非常简单小巧的流量实时监控工具,贵在不需要安装,Linux 操作系统自带,在不出外网的环境中很是实用. watch -d ifstat eth1 如果连 ifstat 都没有的环境中也可以使用 ifc ...

  8. 使用XCA自制CA证书并签发https证书

    序言 本文目的是使公司内网部署的Web可以使用https的方式访问 现有部署的系统有用域名访问,有用IP访问,但都是用http的方式 所以打算在公司内网部署统一的CA证书,并可以自己签发对应的域名和I ...

  9. Expander展开收缩动画

    这个问题困扰了我一天,最后下了个MaterialDesign的demo,看了下他的源码,才恍然大悟,原来很简单. 我原来的设想是在expander的ControlTemplate设置触发器,在IsEx ...

  10. Python读Excel数据自动化填入日常办公的网页表单

      前言 本篇内容,让你完全掌握Python是如何自动化办公的~ 一.环境准备 1.1  Python 3.7.0 1.2  Pycharm  (Python 开发工具) 1.3 Selenium  ...