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

記一次 某智能制造MES系統(tǒng)CPU 爆高分析

系統(tǒng) 其他OS
一般來說cpu的跌宕起伏都是由 thread 誘發(fā)的,一個好的思路就是看下此時各個線程都在做什么,可以使用 ~*e !clrstack 觀察,經(jīng)過仔細對比發(fā)現(xiàn)有 4 處 SqlDataReader 貌似在讀什么東西,剛好對應(yīng)到了 CPU 核數(shù)。

一:背景

1. 講故事

前段時間有位朋友找到我,說他 docker 中的web服務(wù)深夜cpu被打滿,讓我?guī)兔匆幌?,很多朋友問docker中怎么抓dump,我一般都推薦使用 procdump 這款自動化工具,誰用誰知道,有了 dump 之后,接下來就是分析了。

二:WinDbg 分析

1. cpu 真的爆高嗎

有很多朋友問 linux 上的dump可以用 windbg 分析嗎?這里統(tǒng)一回復(fù)下,是可以的,現(xiàn)在的 WinDbg 可以全平臺分析,不信看下圖:

圖片

不過有一點吐槽的是,Linux 不是微軟的,所以在 操作系統(tǒng)層級 上的調(diào)試支持是不夠的,也不是 WinDbg 能力所觸及范圍之內(nèi),所以相比 Windows 有很多的不便。

接下來我們用 !tp 看一下當前的 cpu 到底是多少?

0:000> !tp
CPU utilization: 393 %
Worker Thread: Total: 19 Running: 5 Idle: 10 MaxLimit: 32767 MinLimit: 4
Work Request in Queue: 0
--------------------------------------
Number of Timers: 4
--------------------------------------
Completion Port Thread:Total: 0 Free: 0 MaxFree: 8 CurrentLimit: 0 MaxLimit: 1000 MinLimit: 4

從卦中看當前的 cpu=393% ,這表示什么意思呢?在Linux上是這樣的,一個核占用 100%,可以理解成當前有 4 個核被打滿。

那當前 docker 中給了多少 cpu 核呢?在 Windows 平臺上可以用 !cpuid,在 Linux 上肯定用不了了,沒關(guān)系,熟悉 CLR 的朋友應(yīng)該知道,ServerGC 的heap個數(shù)默認按照cpu 的個數(shù)來的,也就是說當前多少個heap,也就有多少個 cpu core。

有了這個思路,使用 !eeversion 來看下 gc 模式吧。

0:000> !eeversion
4.700.21.56803 (3.x runtime)
4.700.21.56803 @Commit: 28bb6f994c28bc91f09bc0ddb5dcb51d0f066806
Server mode with 4 gc heaps
SOS Version: 7.0.8.10101 retail build

從卦中的 Server mode with 4 gc heaps 來看,當前docker使用 4 個 cpu 核,所以 393% 就表示了當前被完全打滿。

2. 為什么會被打滿

一般來說cpu的跌宕起伏都是由 thread 誘發(fā)的,一個好的思路就是看下此時各個線程都在做什么,可以使用 ~*e !clrstack 觀察,經(jīng)過仔細對比發(fā)現(xiàn)有 4 處 SqlDataReader 貌似在讀什么東西,剛好對應(yīng)到了 CPU 核數(shù),輸出如下:

0:000> ~*e !clrstack
OS Thread Id: 0x3f89 (24)
        Child SP               IP Call Site
00007F9FA14A0628 00007fa4803e2a93 System.Data.SqlClient.TdsParser.TrySkipValue(System.Data.SqlClient.SqlMetaDataPriv, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4399]
00007F9FA14A0640 00007fa47f9a5e03 System.Data.SqlClient.TdsParser.TrySkipRow(System.Data.SqlClient._SqlMetaDataSet, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4334]
00007F9FA14A0670 00007fa4803d2fba System.Data.SqlClient.SqlDataReader.TryCleanPartialRead() [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 760]
00007F9FA14A0690 00007fa47f99e424 System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean, Boolean ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 3286]
00007F9FA14A06F0 00007fa4804742e5 System.Data.SqlClient.SqlDataReader+c__DisplayClass190_0.b__1(System.Threading.Tasks.Task) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 4448]
00007F9FA14A0720 00007fa480a239ea System.Data.SqlClient.SqlDataReader+c__DisplayClass194_0`1[[System.Boolean, System.Private.CoreLib]].b__0(System.Threading.Tasks.Task`1<System.Object>) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 4804]
00007F9FA14A0770 00007fa4803fa6ce System.Threading.Tasks.ContinuationResultTaskFromResultTask`2[[System.__Canon, System.Private.CoreLib],[System.__Canon, System.Private.CoreLib]].InnerInvoke() [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs @ 191]
00007F9FA14A07B0 00007fa4803d5551 System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [/_/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @ 315]
00007F9FA14A07F0 00007fa4803d1c2c System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2421]
00007F9FA14A0870 00007fa4803b99a9 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @ 699]
00007F9FA14A0C80 00007fa4f11512df [DebuggerU2MCatchHandlerFrame: 00007f9fa14a0c80] 
OS Thread Id: 0x3f8a (25)
        Child SP               IP Call Site
00007F9FA3154580 00007fa4803bc857 System.Data.SqlClient.TdsParser.TryGetTokenLength(Byte, System.Data.SqlClient.TdsParserStateObject, Int32 ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 5889]
...
00007F9FA3154670 00007fa4803d2fba System.Data.SqlClient.SqlDataReader.TryCleanPartialRead() [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 760]
00007F9FA3154690 00007fa47f99e424 System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean, Boolean ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 3286]
...
00007F9FA3154870 00007fa4803b99a9 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @ 699]
00007F9FA3154C80 00007fa4f11512df [DebuggerU2MCatchHandlerFrame: 00007f9fa3154c80] 
OS Thread Id: 0x5211 (37)
        Child SP               IP Call Site
00007F9FD2FFC570 00007fa4803bc921 System.Data.SqlClient.TdsParserStateObject.TryReadUInt16(UInt16 ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParserStateObject.cs @ 1519]
00007F9FD2FFC580 00007fa4803bc891 System.Data.SqlClient.TdsParser.TryGetTokenLength(Byte, System.Data.SqlClient.TdsParserStateObject, Int32 ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 5889]
00007F9FD2FFC5C0 00007fa4803e2c06 System.Data.SqlClient.TdsParser.TrySkipValue(System.Data.SqlClient.SqlMetaDataPriv, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4399]
00007F9FD2FFC640 00007fa47f9a5e03 System.Data.SqlClient.TdsParser.TrySkipRow(System.Data.SqlClient._SqlMetaDataSet, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4334]
...
00007F9FD2FFC870 00007fa4803b99a9 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @ 699]
00007F9FD2FFCC80 00007fa4f11512df [DebuggerU2MCatchHandlerFrame: 00007f9fd2ffcc80] 
OS Thread Id: 0x5212 (38)
        Child SP               IP Call Site
00007F9FB3FFE580 00007fa4803bc839 System.Data.SqlClient.TdsParser.TryGetTokenLength(Byte, System.Data.SqlClient.TdsParserStateObject, Int32 ByRef) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 5889]
00007F9FB3FFE5C0 00007fa4803e2c06 System.Data.SqlClient.TdsParser.TrySkipValue(System.Data.SqlClient.SqlMetaDataPriv, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4399]
00007F9FB3FFE640 00007fa47f9a5e03 System.Data.SqlClient.TdsParser.TrySkipRow(System.Data.SqlClient._SqlMetaDataSet, Int32, System.Data.SqlClient.TdsParserStateObject) [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs @ 4334]
00007F9FB3FFE670 00007fa4803d2fba System.Data.SqlClient.SqlDataReader.TryCleanPartialRead() [/_/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs @ 760]
...
00007F9FB3FFE7F0 00007fa4803d1c2c System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread) [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @ 2421]
00007F9FB3FFE870 00007fa4803b99a9 System.Threading.ThreadPoolWorkQueue.Dispatch() [/_/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @ 699]
00007F9FB3FFEC80 00007fa4f11512df [DebuggerU2MCatchHandlerFrame: 00007f9fb3ffec80]

從卦中看,雖然異步寫的很爽,可逆向分析起來真的是上刀山下火海。。。接下來思路在哪里呢?可以這么想,既然是和 SqlDataReader 有關(guān)系,那就挖一挖,看看里面有什么sql。

0:025> !dso
OS Thread Id: 0x3f8a (25)
RSP/REG          Object           Name
rdx              00007fa128ad9c08 System.Data.SqlClient.SNI.TdsParserStateObjectManaged
rdi              00007fa128ad9c08 System.Data.SqlClient.SNI.TdsParserStateObjectManaged
r9               00007fa128ad9c08 System.Data.SqlClient.SNI.TdsParserStateObjectManaged
r12              00007fa128ad9c08 System.Data.SqlClient.SNI.TdsParserStateObjectManaged
r13              00007fa128ad9b70 System.Data.SqlClient.TdsParser
...
00007F9FA31546B0 00007fa3297b8fb8 System.Data.SqlClient.SqlDataReader
...

0:025> !DumpObj /d 00007fa3297b84d0
Name:        System.String
MethodTable: 00007fa477db0f90
EEClass:     00007fa477d1e230
Size:        2496(0x9c0) bytes
File:        /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.22/System.Private.CoreLib.dll
String:      select xxx,xxx,xxx,xxx from template_xxxreport where 1=1 
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
00007fa477daa0e8  400022a        8         System.Int32  1 instance             1237 _stringLength
00007fa477da6f00  400022b        c          System.Char  1 instance               73 _firstChar
00007fa477db0f90  400022c      108        System.String  0   static 00007fa027fff360 Empty

從 sql 看貌似是讀了 template_xxxreport 表, 而且還沒有篩選條件,看樣子是深夜跑什么數(shù)據(jù)把 CPU 給抬起來了,那接下里的問題是什么地方會執(zhí)行這條sql呢?

3. 到底在哪里執(zhí)行的

剛才的線程??床坏揭痪溆脩舸a,我們還可以用 !gcroot 追蹤下這個 sql 的祖宗,可能會有新的發(fā)現(xiàn)哦。

0:025> !gcroot 00007fa3297b84d0
    00007F9FA3154770 00007FA4803FA6CE System.Threading.Tasks.ContinuationResultTaskFromResultTask`2[[System.__Canon, System.Private.CoreLib],[System.__Canon, System.Private.CoreLib]].InnerInvoke() [/_/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs @ 191]
        rbx: 
            ->  00007FA233579680 System.Threading.Tasks.ContinuationResultTaskFromResultTask`2[[System.Object, System.Private.CoreLib],[System.Threading.Tasks.Task`1[[System.Boolean, System.Private.CoreLib]], System.Private.CoreLib]]
            ->  00007FA233579748 System.Threading.Tasks.UnwrapPromise`1[[System.Boolean, System.Private.CoreLib]]
            ...
            ->  00007FA329BE4BB0 System.Threading.Tasks.StandardTaskContinuation
            ->  00007FA329BE4B18 System.Threading.Tasks.ContinuationTaskFromResultTask`1[[System.Boolean, System.Private.CoreLib]]
            ->  00007FA329BE4AD8 System.Action`1[[System.Threading.Tasks.Task`1[[System.Boolean, System.Private.CoreLib]], System.Private.CoreLib]]
            ->  00007FA329BE2AE8 System.Data.SqlClient.SqlDataReader+<>c__DisplayClass195_0`1[[System.Boolean, System.Private.CoreLib]]
            ->  00007FA32982AE50 System.Threading.Tasks.TaskCompletionSource`1[[System.Boolean, System.Private.CoreLib]]
            ->  00007FA32982AE68 System.Threading.Tasks.Task`1[[System.Boolean, System.Private.CoreLib]]
            ->  00007FA3297B91B0 System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[[xxx.xxx.Template_xxxxReport, xxx.xxx],[Dapper.SqlMapper+<QueryRowAsync>d__34`1[[xxx.xxxx.Template_xxxxReport, xxx.xxxx]], Dapper]]
            ->  00007FA3297B84D0 System.String

從引用鏈條看,這條sql使用 Dapper 的 QueryRowAsync 查詢,實體類是 xxx.xxxx.Template_xxxxReport,有了這些信息就好辦了,反饋給朋友后,讓朋友看下這是哪里的sql和model。

據(jù)朋友調(diào)查后,說是用的某商業(yè)數(shù)據(jù)訪問sdk 內(nèi)部邏輯不嚴謹造成的,參考代碼如下:

public async Task<T> FindEntity<T>(object param) where T : class
    {
        //核心問題
        if (param == null)
        {
            param = new { };
        }

        var parameters = param.ToObject();

        //參數(shù)拼接
        foreach (var item in parameters)
        {
            // xxxxx
        }
    }

當 param =null 時,底層用 param = new { }; 當無參數(shù)處理,這就導(dǎo)致全表sql的發(fā)生,朋友說現(xiàn)在想想都有點后怕。。。

圖片

三:總結(jié)

這次事故主要是由 某商業(yè)數(shù)據(jù)訪問sdk 在異常參數(shù)處理時邏輯不嚴謹所致,畢竟 拋異常 比 全量查詢 要好得多,大家在買商業(yè)組件的時候,且行且珍惜。

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

2024-08-08 11:21:01

2021-10-27 07:30:32

.NETCPU論壇

2022-10-24 07:48:37

.NETCPUGC

2024-03-15 15:15:53

.NETCPU系統(tǒng)

2021-05-17 07:43:06

Web站 CPU.NET

2023-07-31 22:29:20

CPU.NETAPI

2024-12-31 09:36:06

2023-11-01 10:46:12

.NET線程同步

2021-04-21 07:38:41

CPU游戲站程序

2022-10-10 17:52:08

CPUERP系統(tǒng)

2024-11-29 10:06:59

2022-02-23 10:12:58

CPUWeb.NET

2023-05-08 08:25:52

2023-09-26 01:11:58

MES非托管泄露

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)

2024-07-01 13:00:24

.NET網(wǎng)絡(luò)邊緣計算

2022-01-17 21:28:36

管理系統(tǒng).NET
點贊
收藏

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