自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

記一次 .NET某網(wǎng)絡(luò)邊緣計(jì)算系統(tǒng) 卡死分析

開發(fā) 前端
網(wǎng)絡(luò)邊緣計(jì)算是一種計(jì)算模型,它將計(jì)算能力和數(shù)據(jù)存儲位置從傳統(tǒng)的集中式數(shù)據(jù)中心向網(wǎng)絡(luò)邊緣的用戶設(shè)備、傳感器和其他物聯(lián)網(wǎng)設(shè)備移動。

一、背景

1. 講故事

早就聽說過有什么 網(wǎng)絡(luò)邊緣計(jì)算,這次還真給遇到了,有點(diǎn)意思,問了下 chatgpt 這是干嘛的 ?

網(wǎng)絡(luò)邊緣計(jì)算是一種計(jì)算模型,它將計(jì)算能力和數(shù)據(jù)存儲位置從傳統(tǒng)的集中式數(shù)據(jù)中心向網(wǎng)絡(luò)邊緣的用戶設(shè)備、傳感器和其他物聯(lián)網(wǎng)設(shè)備移動。這種模型的目的是在接近數(shù)據(jù)生成源頭的地方提供更快速的計(jì)算和數(shù)據(jù)處理能力,從而減少數(shù)據(jù)傳輸延遲并提高服務(wù)質(zhì)量。網(wǎng)絡(luò)邊緣計(jì)算使得在設(shè)備本地進(jìn)行數(shù)據(jù)處理和決策成為可能,同時(shí)也有助于減輕對中心數(shù)據(jù)中心的網(wǎng)絡(luò)流量和負(fù)載。

看到.NET還有這樣的應(yīng)用場景還是挺欣慰的,接下來就來分析下這個(gè)dump到底是怎么回事?

二、WinDbg 分析

1. 為什么會卡死

不同程序的卡死有不同的分析方式,所以要先鑒別下程序的類型以及主線程的調(diào)用棧即可,參考如下:

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

從卦中的指標(biāo)來看,這是一個(gè) Linux 上部署的 Web網(wǎng)站,既然是網(wǎng)站的卡死,那就要關(guān)注各個(gè)線程都在做什么。

2. 線程都在干嘛

以我多年的分析經(jīng)驗(yàn),絕大多數(shù)都是由于 線程饑餓 或者說 線程池耗盡 導(dǎo)致的,首先我們看下線程池的情況。

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

從卦中看當(dāng)前有 365 個(gè)托管線程,這個(gè)算多嗎?對于64core 來說,這個(gè)線程其實(shí)算是正常,訓(xùn)練營里的朋友都知道,server版的gc僅gc線程就有 64*2=128 個(gè),接下來再看一個(gè)指標(biāo)就是當(dāng)前是否存在任務(wù)積壓?可以使用 !ext tpq 命令,參考輸出如下:

0:000> !ext tpq
global work item queue________________________________

local per thread work items_____________________________________

從卦中看當(dāng)前沒有任務(wù)積壓,這就有點(diǎn)反經(jīng)驗(yàn)了。

3. 真的不是線程饑餓嗎

最后一招比較徹底,就是看各個(gè)線程棧都在做什么,可以使用 ~*e !clrstack 命令。

這不看不知道,一看嚇一跳,有 193 個(gè)線程在 Task.Result 上等待,這玩意太經(jīng)典了,然后從上面的調(diào)用棧 UIUpdateTimer_Elapsed 來看,貌似是一個(gè)定時(shí)器導(dǎo)致的,接下來我就好奇這代碼是怎么寫的?

分析上面的代碼之后,我發(fā)現(xiàn)它是和 Linux Shell 窗口進(jìn)行命令交互,不知道為何 Shell 沒有響應(yīng)導(dǎo)致代碼在這里卡死。

4. 為什么線程池沒有積壓

相信有很多朋友對這個(gè)反經(jīng)驗(yàn)的東西很好奇為什么請求沒有積壓在線程池,其實(shí)這個(gè)考驗(yàn)的是你對 PortableThreadPool 的底層了解,這里我就簡單說一下吧。

  • 在 ThreadPool 中有一個(gè) GateThread 線程是專門給線程池動態(tài)注入線程的,參考代碼如下:
private static class GateThread
{
    private static void GateThreadStart()
    {
        while (true)
        {
            bool wasSignaledToWake = DelayEvent.WaitOne((int)delayHelper.GetNextDelay(tickCount));

            WorkerThread.MaybeAddWorkingWorker(threadPoolInstance);
        }
    }
}
  • 一旦有人調(diào)用了 Task.Result 代碼,內(nèi)部會主動喚醒 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);
}

上面這種主動喚醒的機(jī)制是 C# 版 PortableThreadPool 做的優(yōu)化來緩解線程饑餓的,這里有一個(gè)重點(diǎn)就是它只能緩解,換句話說如果上游太猛了還是會有請求積壓的,但為什么這里沒有積壓呢?很顯然上游不猛唄,那如何眼見為實(shí)呢?這就需要看 timer 的周期數(shù)即可,到當(dāng)前的線程棧上給扒出來。

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

從卦中看當(dāng)前是 3s 為一個(gè)周期,這就能解釋為什么線程池沒有積壓的底層原因了。

三、總結(jié)

這個(gè)卡死事故還是蠻好解決的,如果有一些經(jīng)驗(yàn)直接用dotnet-counter也是能搞定的,重點(diǎn)在于這是一個(gè) Linux的dump,同時(shí)又是 .NET上的一個(gè)很好玩的場景,故此分享出來。

責(zé)任編輯:武曉燕 來源: 一線碼農(nóng)聊技術(shù)
相關(guān)推薦

2022-01-17 21:28:36

管理系統(tǒng).NET

2024-11-29 10:06:59

2022-10-13 18:40:05

.NETOA后端

2023-09-27 07:23:10

.NET監(jiān)控軟件

2024-05-20 09:39:02

.NETurl線程池

2023-05-15 11:15:50

.NET門診語句

2024-09-14 10:28:56

.NET卡死程序

2024-06-06 10:51:15

自動化系統(tǒng)推測

2024-05-28 10:18:30

WPF程序數(shù)據(jù)

2024-03-28 12:56:36

2023-04-06 10:52:18

2023-03-26 20:24:50

ERP網(wǎng)站系統(tǒng)

2024-03-26 00:44:53

.NETCIM系統(tǒng)

2023-06-29 17:55:00

.NET日志WinDbg

2024-07-09 11:51:20

Windows線程池源碼

2021-11-02 07:54:41

內(nèi)存.NET 系統(tǒng)

2024-06-04 10:54:34

.NET代碼程序

2024-08-08 11:21:01

2023-06-26 00:12:46

2024-12-27 13:31:18

.NETdump調(diào)試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號