背景 昨天,一位朋友找到我尋求幫助。他的項目需要調用一個第三方項目的webAPI。這個webAPI本身可從header, query string中取相關信息,但同事發現他在調用時,無法按期望的那樣從query string中傳參數給到第三方webAPI (webAPI仿佛忽略了從query str ...
背景
昨天,一位朋友找到我尋求幫助。他的項目需要調用一個第三方項目的webAPI。這個webAPI本身可從header, query string中取相關信息,但同事發現他在調用時,無法按期望的那樣從query string中傳參數給到第三方webAPI (webAPI仿佛忽略了從query string過來的信息),朋友不知道是這個webAPI的問題,還是自己調用代碼的問題了。。
由於這個webAPI service是他們公司內部的某team的項目,所以朋友雖然可以看到源碼,但他並不能快速確定原因, 維護項目的人又不好找。通過webAPI service代碼他自己找到了可疑的原因是webAPI中的這個方法有可能阻擋了他期望的webAPI行為: Instance.EnableFallback() (公司隱私,改了名), 但他無法確定這個方法在實際運行的時候的具體返回值。
聽了朋友介紹,我能想到的一個方法是看一下他們公司的這個第三方的service進程的內部情況 (非生產環境,許可權是允許的)
分析
通過kubectl exec -it [namespace:pod] /bin/bash,我們成功進入了service的pod里。雖然是非生產環境,我們也儘量別打擾人家幹活 那麼…就選擇dump一下運行的dotnet進程嘍
由於這次的任務是觀察托管環境的某個記憶體位置的值,我選擇了用dotnet-dump
然後dotnet-dump analyze core_123 開始分析。
我們想要的是 Instance.EnableFallback 的返回值,而我的朋友已經知道這個Instance的type,所以用dumpheap -type找一下這個instance在哪裡:
然後用!do一下instance具體內容:
1 > do 796f3840d080 2 Name: XXX.Common.XXX.XXXInstance 3 MethodTable: 00007970d459d3a8 4 EEClass: 00007970d45a4fc0 5 Size: 80(0x50) bytes 6 File: /app/XXX.dll 7 Fields: 8 MT Field Offset Type VT Attr Value Name 9 00007970d459d9e8 4000016 10 ...XXX]] 0 instance 0000796f3840d130 _evs
根據簡化和隱藏敏感信息後的代碼:
知道了需要繼續用!do 看這個0000796f3840d130:
1 > do 0000796f3840d130 2 Name: System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[XXX.Common.XXX.XXXEnv, XXX]] 3 MethodTable: 00007970d459d718 4 EEClass: 00007970ce610c00 5 Size: 72(0x48) bytes 6 File: /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.32/System.Private.CoreLib.dll 7 Fields: 8 MT Field Offset Type VT Attr Value Name 9 00007970ce636448 4001aec 8 System.Int32[] 0 instance 0000796f384143a8 _buckets 10 00007970ce636250 4001aed 10 ...ivate.CoreLib]][] 0 instance 0000796f384143d0 _entries 11 00007970ce5fa0e8 4001aee 30 System.Int32 1 instance 1 _count
大家如果瞭解.net Dictionary類型的實現,就知道目前這個dictionary是1size且具體的item值可以直接用!dp看:
Dictionary里的_entries是個數組,item類型是value type,所以是inlined memory, 所以直接看0000796f38412948, 因為他是數組中第0個元素里的key-value pair里的value(XXXEnv instance的地址)。
1 > do 0000796f38412948 2 Name: XXX.Common.XXXEnv 3 MethodTable: 00007970d459e700 4 EEClass: 00007970d45a5888 5 Size: 56(0x38) bytes 6 File: /app/XXX.dll 7 Fields: 8 MT Field Offset Type VT Attr Value Name 9 00007970d340a988 400000a 8 ....Config.XXXConfig 0 instance 0000796f382898f0 _toggleConfig
最後看那個_toggleConfig,Instance.EnableFallback()裡面一通調用最終會讀它的內容,簡化代碼如下:
所以繼續!do看一下這個_toggleConfig:
至此原因確定,懷疑的這個方法在當前這個webAPI service下會返回false.
後記
也許有朋友會問,直接dump type是XXXConfig的instance不就行了。是的,不過在這個dump文件中,我發現了不止一個active的XXXConfig instance, 也就是說不止一處會用到這個不唯一的XXXConfig, 而我需要明確Instance.EnableFallback最終的返回,所以需要耐心探索哈
總結
我的朋友知道了他想確定的Instance.EnableFallback在第三方service運行的時候的真實值之後,也明確了他那邊的應對這個webAPI的調用方式了。
這次診斷的問題雖不是cpu過高、記憶體泄漏這類資源問題,但還是用上了與排查資源泄漏相同的底層調試診斷技術來解決。最後我的朋友很高興,吃了個定心丸