Windbg分析高記憶體佔用問題
1. 問題簡介
最近產品釋出大版本補丁更新,一商超客戶升級後,反饋系統經常奔潰,導致超市的收銀系統無法正常收銀,現場排隊付款的顧客更是抱怨聲聲。為了緩解現場的情況, 客戶都是手動回收IIS應用程式池才能解決。
這樣的後果是很嚴重的,接到反饋,第一時間想到的是加記憶體吧,這樣最快。但是客戶從8G-->16G-->32G,只是延長了每次奔潰的時間,但是並沒有解決系統卡頓的問題。到這裡,也基本猜測了問題所在了,肯定是什麼東西一直在吃記憶體且得不到釋放。這種問題,也就只能打Dump分析了。
2. 打Dump
遠端客戶應用伺服器,32G記憶體佔用已經消耗了78%,而現場已經反饋收銀系統接近奔潰了,要求先強制回收記憶體。反正也要奔潰了,先打Dump再說吧。
(PS:打Dump會掛起程序,導致應用無法響應!而打Dump的耗時,也是根據當時程序的記憶體佔用有關,記憶體佔用越大,耗時越久。)
開啟工作管理員,選擇對應的IIS程序,右鍵建立轉儲檔案(Dump)。
結果,Dump檔案是生成的,結果當分析的時候,發現Windbg提示Dump無效。說明Dump檔案建立的有問題。觀察工作管理員,發現記憶體佔用一下就降下來了,原來是之前的程序直接奔潰了,重啟了一個W3WP程序。
既然直接從工作管理員無法建立,就使用第三方工具收集Dump吧。經過Goggle,找到一款很好用的Dump收集工具ProcDump,是一個命令列應用,其主要用途是監視應用程式的CPU或記憶體峰值並在峰值期間生成Dump。
因為是高記憶體佔用問題,我們使用以下命令來抓取dump:
(PS:可以使用程序名稱,也可以使用程序ID來指定要建立Dump的程序。當有多個相同名稱的程序時,必須使用程序ID來指定!)
procdump w3wp -m 20480 -o D:\Dumps (當記憶體超過20G時抓取一個w3wp程序的MiniDump)
上面就是我踩得第一個坑,因為預設抓取的是MiniDump,很快就抓下來,檔案也很小,正在我得意的時候,Windbg載入Dump分析的時候,發現包含的資訊很少,根本無法進行進一步的分析。
調整建立Dump的命令,新增-ma
引數即可建立完整Dump。
procdump w3wp -ma -m 20480 -o D:\Dumps (當記憶體超過20G時抓取一個w3wp程序的完整Dump)
結果再一次,當記憶體佔用到達20G,佔比80%的時候,Dump再次建立失敗,提示:Procdump Error writing dump file
這個坑,也讓我開始真正停下來思考問題。羅馬不是一日建成的,記憶體也不是一下撐爆的。我幹嘛死腦筋非要到記憶體佔用超過80%才去打Dump呢呢呢???!
煥然大悟,如醍醐灌頂。
procdump w3wp -ma -m 8000 -o D:\Dumps (當記憶體超過8000M時抓取一個w3wp程序的完整Dump,並輸出到D:\Dumps資料夾)
此時記憶體佔用在40%左右,這次Dump終於成功建立了。
3..分析Dump
分析Dump,上WinDbg。如果對WinDbg不理解,可以看我這篇WinDbg學習筆記。
接下來就是一通命令亂敲,我儘量解釋清晰。
0:000> !dumpheap -stat //檢查當前所有託管型別的統計資訊
....
00007ffdb9387a98 777101 69462436 System.Char[]
00007ffdb938c988 588917 115563505 System.Byte[]
00007ffdb9389220 1026406 119828936 System.Int32[]
00007ffdb93516a8 663559 128819040 System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[System.Object, mscorlib]][]
00000218c6c30a80 6436865 197832116 Free
00007ffdae9cc240 23171 273333144 System.Collections.Generic.HashSet`1+Slot[[System.String, mscorlib]][]
00007ffdb9391f28 13885170 333244080 System.Boolean
00007ffd5c24a068 14003455 560138200 Kingdee.BOS.JSON.JSONArray
00007ffdb9386fc0 14373648 1393615400 System.Object[]
00007ffdb9386948 76146065 4000287202 System.String
Total 138435970 objects
使用dumpheap -stat
命令檢視當前所有託管型別的統計資訊。從輸出的結果來看:
- 其中佔用記憶體最多當屬
System.String
型別,接近4G的大小(是不是很吃驚?!)。 - 其次
System.Object[]
型別佔有1.3G大小。 Kingdee.BOS.JSON.JSONArray
型別也大概佔用了560M。
我們首先來分析佔用最多的System.String
型別,看看有什麼發現。
0:000> !dumpheap -mt 00007ffdb9386948 -min 200 //檢視200byte以上的string
Address MT Size
...
0000021bcbaf5158 00007ffdb9386948 1140
0000021d375d1038 00007ffdb9386948 149698
0000021d375f5920 00007ffdb9386948 149698
0000021d3765b138 00007ffdb9386948 149706
0000021d37f739c8 00007ffdb9386948 217120
0000021d37fa8a08 00007ffdb9386948 190162
0000021d38047330 00007ffdb9386948 1224698
0000021d3829d348 00007ffdb9386948 1224698
0000021d386bd678 00007ffdb9386948 2610994
0000021d38bb8500 00007ffdb9386948 2610994
Statistics:
MT Count TotalSize Class Name
00007ffdb9386948 10991 76632628 System.String
Total 10991 objects
從上面的輸出可以發現:
- 單個
System.String
型別最大佔用2M以上。 - 超過200byte的位元組的大小的
System.String
總大小也不過76M。(所以我們也不必深究大的String物件。)
那我們索性挑一個小點的物件來看看儲存的是什麼字串,來滿足一下我們的好奇心。
0.000> !do 0000021bcbaf5158 //使用!do命令檢視一個物件的內容
Name: System.String
MethodTable: 00007ffdb9386948
EEClass: 00007ffdb8c850e0
Size: 1140(0x474) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: 5b13710029d012False2052_T_BD_MATERIAL_MATERIAL.FAuxPropertyIdFBaseUnitIdFCategoryIDFChargeIDFCheckIncomingFDefaultVendorFErpClsIDFInvPtyIdFIsAffectPlanFIsAffectPlan1FIsBatchManageFIsComControlFIsEnableFIsEnable1FIsExpParToFlotFIsInventoryFIsPRFIsReturnMaterialFIsSourceControlFIsVmiBusinessFNameFNumberFPlanModeFPurchasePriceUnitIdFPurchaseUnitIdFPurPriceURNomFPurPriceURNumFPurURNomFPurURNumFReceiveAdvanceDaysFReceiveDelayDaysFReceiveMaxScaleFReceiveMinScaleFSalePriceUnitIdFSaleUnitIdFSpecificationFStockIdFStockPlaceIdFStoreUnitIDFTaxTypeFUseOrgId111193
Fields:
MT Field Offset Type VT Attr Value Name
00007ffdb9389288 400026f 8 System.Int32 1 instance 557 m_stringLength
00007ffdb9387b00 4000270 c System.Char 1 instance 35 m_firstChar
00007ffdb9386948 4000274 90 System.String 0 shared static Empty
>> Domain:Value 00000218c6c4d220:NotInit 0000021d52d81840:NotInit <<
似乎是基礎資料欄位資訊。那接下來使用!gcroot
命令檢視其對應的GC根,看看到底是什麼物件持有其引用,導致佔用記憶體得不到釋放。
0:000> !gcroot 0000021bcbaf5158 //使用!gcroot 檢視一個物件的gc根
HandleTable:
00000218c6ff15e8 (pinned handle)
-> 0000021cc75ebe68 System.Object[]
-> 0000021bc7629a10 Kingdee.BOS.Cache.KCacheManagerFactory
-> 0000021bc7629ab8 System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[Kingdee.BOS.Cache.AbstractKCacheManager, Kingdee.BOS]]
-> 0000021c4da6fa48 System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[Kingdee.BOS.Cache.AbstractKCacheManager, Kingdee.BOS]][]
-> 00000218c83861b8 Kingdee.BOS.Cache.KCacheManager
-> 00000218c8386630 Kingdee.BOS.Cache.ECache.ECacheManager
-> 00000218c83866e8 System.Collections.Concurrent.ConcurrentDictionary`2[[System.String, mscorlib],[System.Collections.Generic.HashSet`1[[System.String, mscorlib]], System.Core]]
-> 0000021bcbae0c70 System.Collections.Concurrent.ConcurrentDictionary`2+Tables[[System.String, mscorlib],[System.Collections.Generic.HashSet`1[[System.String, mscorlib]], System.Core]]
-> 0000021bcbad0128 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.String, mscorlib],[System.Collections.Generic.HashSet`1[[System.String, mscorlib]], System.Core]][]
-> 0000021bcbb34bf8 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.String, mscorlib],[System.Collections.Generic.HashSet`1[[System.String, mscorlib]], System.Core]]
-> 0000021bcbada790 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.String, mscorlib],[System.Collections.Generic.HashSet`1[[System.String, mscorlib]], System.Core]]
-> 0000021a49766460 System.Collections.Generic.HashSet`1[[System.String, mscorlib]]
-> 00000219540976b0 System.Collections.Generic.HashSet`1+Slot[[System.String, mscorlib]][]
-> 0000021bcbaf5158 System.String
Found 1 unique roots (run '!GCRoot -all' to see all roots).
從以上輸出可以看出:
- 該String型別被一個Hashset所持有。
- 從
Cache
關鍵字可以看出該String型別是被快取所持有。
分析到這裡,我們大致可以得出一個結論:
String型別佔用4G記憶體,絕大多數是由快取所佔用,才導致String型別得不到釋放。
那我們是不是可以猜測記憶體佔用持續走高是不是被快取撐爆的呢?。
帶著這個疑問我們來繼續分析下Kingdee.BOS.JSON.JSONArray
型別。
0:000> !dumpheap -mt 00007ffd5c24a068 //輸出託管堆上的所有JSONArray物件
Address MT Size
....
0000021975972b48 00007ffd5c24a068 40
00000218c933f060 00007ffd5c24a068 40
00000218c7605990 00007ffd5c24a068 40
00000218c7605af0 00007ffd5c24a068 40
00000218c7605c50 00007ffd5c24a068 40
00000218c7605e18 00007ffd5c24a068 40
00000218c7605fa0 00007ffd5c24a068 40
00000218c7606198 00007ffd5c24a068 40
00000218c7606338 00007ffd5c24a068 40
00000218c76064b0 00007ffd5c24a068 40
User interrupt.
從輸出結果來看:
- 滿屏都是40byte的JSONArray。只能使用
Ctrl+Break
命令中止輸出。
但為了保險期間,我們來驗證下有沒有100byte以上的JSONArray
。
0:000> !dumpheap -mt 00007ffd5c24a068 -min 100
Address MT Size
Statistics:
MT Count TotalSize Class Name
Total 0 objects
這時我們可以大膽猜測所有的JSONArray
物件都是40byte。從而可以得出另一個猜測佔用560M記憶體的JSONArray,都具有相似的物件結構。接下來我們來驗證這個猜測。隨機選擇幾個物件,看看其內容具體是什麼。
0:000> !DumpObj /d 0000021975972b48 //檢視第一個JSONArray
Name: System.Object[]
MethodTable: 00007ffdb9386fc0
EEClass: 00007ffdb8d4aa00
Size: 88(0x58) bytes
Array: Rank 1, Number of elements 8, Type CLASS (Print Array)
Fields:
None
從輸出可以看出:
- JSONArray實質是
System.Object[]
型別。 - 對應的
MethodTable: 00007ffdb9386fc0
。
如果你記性好的話,我們應當還記得佔用記憶體第二多的就是這個System.Object[]
型別,佔用1.3G。翻到上面,你可以發現其MethodTable和上面的統計資訊是一致的。
(PS:到這裡我們是不是可以猜測:System.Object[]
佔用的記憶體無法釋放,就是由於被JSONArray
持有引用導致的呢?)
既然是陣列,就使用!DumpArray
命令來解開陣列的面紗。
0:000> !DumpArray /d 0000021975972b48
Name: System.Object[]
MethodTable: 00007ffdb9386fc0
EEClass: 00007ffdb8d4aa00
Size: 88(0x58) bytes
Array: Rank 1, Number of elements 8, Type CLASS
Element Methodtable: 00007ffdb9386f28
[0] 0000021975972a08
[1] 0000021975972a70
[2] 0000021975972a40
[3] 0000021ac75e87b8
[4] 0000021975972b10
[5] 0000021975972ba0
[6] null
[7] null
0:000> !DumpObj /d 0000021975972a08
Name: System.String
MethodTable: 00007ffdb9386948
EEClass: 00007ffdb8c850e0
Size: 54(0x36) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: 555d8ca25a6261
Fields:7
MT Field Offset Type VT Attr Value Name
00007ffdb9389288 400026f 8 System.Int32 1 instance 14 m_stringLength
00007ffdb9387b00 4000270 c System.Char 1 instance 35 m_firstChar
00007ffdb9386948 4000274 90 System.String 0 shared static Empty
>> Domain:Value 00000218c6c4d220:NotInit 0000021d52d81840:NotInit <<
從以上輸出可以看出,其共有8個子項,我們再隨機挑幾個子項看看是什麼內容。
0:000> !DumpObj /d 0000021975972a70
Name: System.String
MethodTable: 00007ffdb9386948
EEClass: 00007ffdb8c850e0
Size: 42(0x2a) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: FHTZDLB
Fields:
MT Field Offset Type VT Attr Value Name
00007ffdb9389288 400026f 8 System.Int32 1 instance 8 m_stringLength
00007ffdb9387b00 4000270 c System.Char 1 instance 50 m_firstChar
00007ffdb9386948 4000274 90 System.String 0 shared static Empty
>> Domain:Value 00000218c6c4d220:NotInit 0000021d52d81840:NotInit <<
0:000> !DumpObj /d 0000021975972a40
Name: System.String
MethodTable: 00007ffdb9386948
EEClass: 00007ffdb8c850e0
Size: 42(0x2a) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: 發貨通知單列表
Fields:
MT Field Offset Type VT Attr Value Name
00007ffdb9389288 400026f 8 System.Int32 1 instance 8 m_stringLength
00007ffdb9387b00 4000270 c System.Char 1 instance 6279 m_firstChar
00007ffdb9386948 4000274 90 System.String 0 shared static Empty
>> Domain:Value 00000218c6c4d220:NotInit 0000021d52d81840:NotInit <<
我們可以看到一個字串內容是FHTZDLB
,另一個是發貨通知單列表
。看到這,我立馬就條件反射的想到,這不就是我們的選單資訊嘛。為了驗證我的想法,連續檢視幾個JSONArray
,都是相似的內容。
這時,我們繼續發揚敢猜敢做的精神。是不是記憶體被選單快取撐爆的?!
為了驗證這一猜測,我們繼續從Dump中尋找佐證。使用~* e!clrstack
來看看所有執行緒的呼叫堆疊吧。
0:000> ~* e!clrstack
OS Thread Id: 0x11dc (0)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
Failed to start stack walk: 80070057
OS Thread Id: 0x2b2c (28)
Child SP IP Call Site
00000076cff7ecc8 00007ffdca2e6bf4 [HelperMethodFrame_1OBJ: 00000076cff7ecc8] System.Threading.WaitHandle.WaitMultiple(System.Threading.WaitHandle[], Int32, Boolean, Boolean)
00000076cff7ee00 00007ffdb91af67c System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], Int32, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\waithandle.cs @ 454]
00000076cff7ee60 00007ffdb201b2fb System.Net.TimerThread.ThreadProc()
00000076cff7ef10 00007ffdb915ca72 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 954]
00000076cff7efe0 00007ffdb915c904 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 902]
00000076cff7f010 00007ffdb915c8c2 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 891]
00000076cff7f060 00007ffdb9196472 System.Threading.ThreadHelper.ThreadStart() [f:\dd\ndp\clr\src\BCL\system\threading\thread.cs @ 111]
00000076cff7f2b8 00007ffdbb4f6793 [GCFrame: 00000076cff7f2b8]
00000076cff7f608 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076cff7f608]
00000076cff7f798 00007ffdbb4f6793 [ContextTransitionFrame: 00000076cff7f798]
00000076cff7f9c8 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076cff7f9c8]
OS Thread Id: 0x1bd4 (133)
Child SP IP Call Site
GetFrameContext failed: 1
0000000000000000 0000000000000000
OS Thread Id: 0x1a98 (134)
Child SP IP Call Site
00000076dbdbcc88 00007ffdca2e6124 [InlinedCallFrame: 00000076dbdbcc88] .SNIReadSyncOverAsync(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbdbcc88 00007ffdaaaf5dd4 [InlinedCallFrame: 00000076dbdbcc88] .SNIReadSyncOverAsync(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbdbcc60 00007ffdaaaf5dd4 DomainNeutralILStubClass.IL_STUB_PInvoke(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbdbcd10 00007ffdaab08fe3 SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle, IntPtr ByRef, Int32)
00000076dbdbcd70 00007ffdaabe0ae0 System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
00000076dbdbcdd0 00007ffdaabe09dd System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
00000076dbdbce10 00007ffdaabdf7f5 System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
00000076dbdbce50 00007ffdaabdfa0e System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte ByRef)
00000076dbdbce90 00007ffdaabc7daa System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior, System.Data.SqlClient.SqlCommand, System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.BulkCopySimpleResultSet, System.Data.SqlClient.TdsParserStateObject, Boolean ByRef)
00000076dbdbcff0 00007ffdaabbb3c7 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
00000076dbdbd050 00007ffdaabb8325 System.Data.SqlClient.SqlDataReader.get_MetaData()
00000076dbdbd0a0 00007ffdaab3be73 System.Data.SqlClient.SqlCommand.FinishExecuteReader(System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.RunBehavior, System.String, Boolean, Boolean)
00000076dbdbd110 00007ffdaab3b75f System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, Boolean, Int32, System.Threading.Tasks.Task ByRef, Boolean, Boolean, System.Data.SqlClient.SqlDataReader, Boolean)
00000076dbdbd1f0 00007ffdaab3a763 System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String, System.Threading.Tasks.TaskCompletionSource`1, Int32, System.Threading.Tasks.Task ByRef, Boolean ByRef, Boolean, Boolean)
00000076dbdbd2c0 00007ffdaab3a49b System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String)
00000076dbdbd360 00007ffdaab35cc6 System.Data.SqlClient.SqlCommand.ExecuteReader(System.Data.CommandBehavior, System.String)
00000076dbdbd3f0 00007ffd5c517ead Kingdee.BOS.App.Data.AbstractDatabase.DoExecuteReader(System.Data.Common.DbCommand, System.Data.CommandBehavior)
00000076dbdbd450 00007ffd5c515ebb Kingdee.BOS.App.Data.AbstractDatabase.ExecuteReader(System.Data.Common.DbCommand, System.Collections.Generic.IEnumerable`1, System.Data.CommandBehavior, Boolean)
00000076dbdbd4d0 00007ffd5c4fd6f2 Kingdee.BOS.App.Data.AbstractDatabase.ExecuteReader(System.Data.Common.DbCommand, System.Collections.Generic.IEnumerable`1, System.Data.CommandBehavior)
00000076dbdbd500 00007ffd5c4e31b1 Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Collections.Generic.IEnumerable`1, System.Data.CommandType, System.Data.CommandBehavior, Boolean)
00000076dbdbd570 00007ffd5c51d2a7 Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Collections.Generic.IEnumerable`1, System.Data.CommandType, Boolean)
00000076dbdbd5b0 00007ffd5c51d2fc Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Data.CommandType, Boolean)
00000076dbdbd5e0 00007ffd5c51d341 Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String)
00000076dbdbd610 00007ffd5ca5a5d4 Kingdee.BOS.App.Core.MainConsole.MainConsoleServer.GetSearchMenuData(Kingdee.BOS.Context, System.String, System.Collections.Generic.HashSet`1 ByRef, System.Collections.Generic.HashSet`1 ByRef)
00000076dbdbd7d0 00007ffd5ca58164 Kingdee.BOS.App.Core.MainConsole.MainConsoleServer.GetMenuArrayForCache(Kingdee.BOS.Context)
00000076dbdbda78 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076dbdbda78]
00000076dbdbddb8 00007ffdbb4f6793 [HelperMethodFrame_PROTECTOBJ: 00000076dbdbddb8] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
00000076dbdbdf30 00007ffdb914b690 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[]) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 761]
00000076dbdbdfa0 00007ffdb9142922 System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 735]
00000076dbdbe020 00007ffdb9143f22 System.Reflection.MethodBase.Invoke(System.Object, System.Object[]) [f:\dd\ndp\clr\src\BCL\system\reflection\methodbase.cs @ 211]
00000076dbdbe060 00007ffd5c61990c Microsoft.Practices.Unity.InterceptionExtension.InterceptingRealProxy+c__DisplayClass1.b__0(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextInterceptionBehaviorDelegate)
00000076dbdbe160 00007ffd5c619477 Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior+c__DisplayClass1.b__0(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbdbe200 00007ffd5c61cbc4 Kingdee.BOS.Cache.KCacheMethodCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbdbe350 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbdbe3e0 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbdbe470 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbdbe500 00007ffd5c61936d Microsoft.Practices.Unity.InterceptionExtension.HandlerPipeline.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.InvokeHandlerDelegate)
00000076dbdbe590 00007ffd5c618999 Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextInterceptionBehaviorDelegate)
00000076dbdbe620 00007ffd5c61845d Microsoft.Practices.Unity.InterceptionExtension.InterceptionBehaviorPipeline.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.InvokeInterceptionBehaviorDelegate)
00000076dbdbe6b0 00007ffd5c617002 Microsoft.Practices.Unity.InterceptionExtension.InterceptingRealProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)
00000076dbdbe790 00007ffdb911190c System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32) [f:\dd\ndp\clr\src\BCL\system\runtime\remoting\realproxy.cs @ 823]
00000076dbdbe980 00007ffdbb4f4a02 [TPMethodFrame: 00000076dbdbe980] Kingdee.BOS.Contracts.IMainConsoleServer.GetMenuArrayForCache(Kingdee.BOS.Context)
00000076dbdbec00 00007ffdb91ad436 System.Threading.Tasks.Task.Execute() [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 2498]
00000076dbdbec40 00007ffdb915ca72 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 954]
00000076dbdbed10 00007ffdb915c904 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs @ 902]
00000076dbdbed40 00007ffdb91ad6dc System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef) [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 2827]
00000076dbdbedf0 00007ffdb91acdf3 System.Threading.Tasks.Task.ExecuteEntry(Boolean) [f:\dd\ndp\clr\src\BCL\system\threading\Tasks\Task.cs @ 2767]
00000076dbdbee30 00007ffdb9194882 System.Threading.ThreadPoolWorkQueue.Dispatch() [f:\dd\ndp\clr\src\BCL\system\threading\threadpool.cs @ 820]
00000076dbdbf2c8 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076dbdbf2c8]
00000076dbdbf458 00007ffdbb4f6793 [ContextTransitionFrame: 00000076dbdbf458]
00000076dbdbf688 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076dbdbf688]
OS Thread Id: 0x153c (135)
Child SP IP Call Site
GetFrameContext failed: 1
0000000000000000 0000000000000000
OS Thread Id: 0x242c (136)
Child SP IP Call Site
GetFrameContext failed: 1
0000000000000000 0000000000000000
OS Thread Id: 0x153c (135)
Child SP IP Call Site
GetFrameContext failed: 1
0000000000000000 0000000000000000
OS Thread Id: 0x242c (136)
Child SP IP Call Site
GetFrameContext failed: 1
0000000000000000 0000000000000000
OS Thread Id: 0x2a04 (137)
Child SP IP Call Site
00000076dbf7af08 00007ffdca2e6124 [InlinedCallFrame: 00000076dbf7af08] .SNIReadSyncOverAsync(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbf7af08 00007ffdaaaf5dd4 [InlinedCallFrame: 00000076dbf7af08] .SNIReadSyncOverAsync(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbf7aee0 00007ffdaaaf5dd4 DomainNeutralILStubClass.IL_STUB_PInvoke(SNI_ConnWrapper*, SNI_Packet**, Int32)
00000076dbf7af90 00007ffdaab08fe3 SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle, IntPtr ByRef, Int32)
00000076dbf7aff0 00007ffdaabe0ae0 System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
00000076dbf7b050 00007ffdaabe09dd System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
00000076dbf7b090 00007ffdaabdf7f5 System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
00000076dbf7b0d0 00007ffdaabdfa0e System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte ByRef)
00000076dbf7b110 00007ffdaabc7daa System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior, System.Data.SqlClient.SqlCommand, System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.BulkCopySimpleResultSet, System.Data.SqlClient.TdsParserStateObject, Boolean ByRef)
00000076dbf7b270 00007ffdaabbb3c7 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
00000076dbf7b2d0 00007ffdaabb8325 System.Data.SqlClient.SqlDataReader.get_MetaData()
00000076dbf7b320 00007ffdaab3be73 System.Data.SqlClient.SqlCommand.FinishExecuteReader(System.Data.SqlClient.SqlDataReader, System.Data.SqlClient.RunBehavior, System.String, Boolean, Boolean)
00000076dbf7b390 00007ffdaab3b75f System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, Boolean, Int32, System.Threading.Tasks.Task ByRef, Boolean, Boolean, System.Data.SqlClient.SqlDataReader, Boolean)
00000076dbf7b470 00007ffdaab3a763 System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String, System.Threading.Tasks.TaskCompletionSource`1, Int32, System.Threading.Tasks.Task ByRef, Boolean ByRef, Boolean, Boolean)
00000076dbf7b540 00007ffdaab3a49b System.Data.SqlClient.SqlCommand.RunExecuteReader(System.Data.CommandBehavior, System.Data.SqlClient.RunBehavior, Boolean, System.String)
00000076dbf7b5e0 00007ffdaab35cc6 System.Data.SqlClient.SqlCommand.ExecuteReader(System.Data.CommandBehavior, System.String)
00000076dbf7b670 00007ffd5c517ead Kingdee.BOS.App.Data.AbstractDatabase.DoExecuteReader(System.Data.Common.DbCommand, System.Data.CommandBehavior)
00000076dbf7b6d0 00007ffd5c515ebb Kingdee.BOS.App.Data.AbstractDatabase.ExecuteReader(System.Data.Common.DbCommand, System.Collections.Generic.IEnumerable`1, System.Data.CommandBehavior, Boolean)
00000076dbf7b750 00007ffd5c4fd6f2 Kingdee.BOS.App.Data.AbstractDatabase.ExecuteReader(System.Data.Common.DbCommand, System.Collections.Generic.IEnumerable`1, System.Data.CommandBehavior)
00000076dbf7b780 00007ffd5c4e31b1 Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Collections.Generic.IEnumerable`1, System.Data.CommandType, System.Data.CommandBehavior, Boolean)
00000076dbf7b7f0 00007ffd5c51d2a7 Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Collections.Generic.IEnumerable`1, System.Data.CommandType, Boolean)
00000076dbf7b830 00007ffd5c61737a Kingdee.BOS.App.Data.DBUtils.ExecuteReader(Kingdee.BOS.Context, System.String, System.Collections.Generic.List`1)
00000076dbf7b860 00007ffd5c8d2bd7 Kingdee.BOS.App.Core.UserParameterService.GetParamter(Kingdee.BOS.Context, Int64, System.String, System.String)
00000076dbf7bb68 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076dbf7bb68]
00000076dbf7bea8 00007ffdbb4f6793 [HelperMethodFrame_PROTECTOBJ: 00000076dbf7bea8] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
00000076dbf7c020 00007ffdb914b690 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[]) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 761]
00000076dbf7c090 00007ffdb9142922 System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 735]
00000076dbf7c110 00007ffdb9143f22 System.Reflection.MethodBase.Invoke(System.Object, System.Object[]) [f:\dd\ndp\clr\src\BCL\system\reflection\methodbase.cs @ 211]
00000076dbf7c150 00007ffd5c61990c Microsoft.Practices.Unity.InterceptionExtension.InterceptingRealProxy+c__DisplayClass1.b__0(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextInterceptionBehaviorDelegate)
00000076dbf7c250 00007ffd5c619477 Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior+c__DisplayClass1.b__0(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbf7c2f0 00007ffd5c61cbc4 Kingdee.BOS.Cache.KCacheMethodCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbf7c440 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbf7c4d0 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbf7c560 00007ffd5c61b10b Kingdee.BOS.Performance.Publisher.PerformanceCallHandler.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate)
00000076dbf7c5f0 00007ffd5c61936d Microsoft.Practices.Unity.InterceptionExtension.HandlerPipeline.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.InvokeHandlerDelegate)
00000076dbf7c680 00007ffd5c618999 Microsoft.Practices.Unity.InterceptionExtension.PolicyInjectionBehavior.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.GetNextInterceptionBehaviorDelegate)
00000076dbf7c710 00007ffd5c61845d Microsoft.Practices.Unity.InterceptionExtension.InterceptionBehaviorPipeline.Invoke(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation, Microsoft.Practices.Unity.InterceptionExtension.InvokeInterceptionBehaviorDelegate)
00000076dbf7c7a0 00007ffd5c617002 Microsoft.Practices.Unity.InterceptionExtension.InterceptingRealProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)
00000076dbf7c880 00007ffdb911190c System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32) [f:\dd\ndp\clr\src\BCL\system\runtime\remoting\realproxy.cs @ 823]
00000076dbf7ca70 00007ffdbb4f4a02 [TPMethodFrame: 00000076dbf7ca70] Kingdee.BOS.Contracts.IUserParameterService.GetParamter(Kingdee.BOS.Context, Int64, System.String, System.String)
00000076dbf7ccf0 00007ffd5c8d28c5 Kingdee.BOS.App.Security.K3CloudLoginService.SetRegionInfo(Kingdee.BOS.Context, Kingdee.BOS.Contracts.IUserParameterService, Kingdee.BOS.Orm.DataEntity.DynamicObject)
00000076dbf7cd70 00007ffd5c22b2e2 Kingdee.BOS.App.Security.K3DataCenterService.GetDataCenterContextByID(System.String)
00000076dbf7cdc0 00007ffd5c227d97 Kingdee.BOS.App.Security.K3CloudLoginService+c__DisplayClass8.b__3(System.String)
00000076dbf7cdf0 00007ffd5c228471 Kingdee.BOS.Core.Authentication.AbstractAuthService.LoadContext(Kingdee.BOS.Core.Authentication.LoadContextArg)
00000076dbf7ce50 00007ffd5c226ed8 Kingdee.BOS.App.Security.K3CloudLoginService.Login(Kingdee.BOS.Performance.Common.PerformanceContext, Kingdee.BOS.Authentication.LoginInfo)
00000076dbf7ced0 00007ffd5c20b5a9 Kingdee.BOS.ServiceHelper.LoginServiceHelper.Login(Kingdee.BOS.Performance.Common.PerformanceContext, System.String, Kingdee.BOS.Authentication.LoginInfo)
00000076dbf7cf30 00007ffd5c20960f Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateLoginInfo(System.String, Kingdee.BOS.Authentication.LoginInfo)
00000076dbf7d080 00007ffd5c20783c Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser(System.String, System.String, System.String, Int32)
00000076dbf7d318 00007ffdbb4f6793 [DebuggerU2MCatchHandlerFrame: 00000076dbf7d318]
00000076dbf7d658 00007ffdbb4f6793 [HelperMethodFrame_PROTECTOBJ: 00000076dbf7d658] System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)
00000076dbf7d7d0 00007ffdb914b690 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[]) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 761]
00000076dbf7d840 00007ffdb9142922 System.Reflection.RuntimeMethodInfo.Invoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo) [f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs @ 735]
00000076dbf7d8c0 00007ffd5c206201 Kingdee.BOS.ServiceFacade.KDServiceFx.ServiceExecutor.Execute(Kingdee.BOS.ServiceFacade.KDServiceFx.KDServiceContext, Kingdee.BOS.ServiceFacade.KDServiceFx.ServiceType, System.String[], Kingdee.BOS.ServiceFacade.SerializerProxy, Kingdee.BOS.ServiceFacade.KDServiceFx.ServiceType)
00000076dbf7d960 00007ffd5c203ea9 Kingdee.BOS.ServiceFacade.KDServiceFx.ExecuteServiceModule.OnProcess(Kingdee.BOS.ServiceFacade.KDServiceFx.KDServiceContext)
00000076dbf7da00 00007ffd5c203ab8 Kingdee.BOS.ServiceFacade.KDServiceFx.ModulePipeline.ExcuteRequest(Kingdee.BOS.ServiceFacade.KDServiceFx.KDServiceContext)
00000076dbf7da50 00007ffd5c20123e Kingdee.BOS.ServiceFacade.KDServiceFx.RequestExcuteRuntime.StartRequest(Kingdee.BOS.ServiceFacade.KDServiceFx.RequestExtractor, Kingdee.BOS.ServiceFacade.KDServiceFx.WebContext)
00000076dbf7daa0 00007ffd5c200f00 Kingdee.BOS.ServiceFacade.KDServiceFx.KDSVCHandler.ExecuteRequest(Kingdee.BOS.ServiceFacade.KDServiceFx.WebContext, Kingdee.BOS.ServiceFacade.KDServiceFx.RequestExtractor)
00000076dbf7dae0 00007ffd5c200d45 Kingdee.BOS.ServiceFacade.KDServiceFx.KDSVCHandler.ProcessRequestInternal(Kingdee.BOS.ServiceFacade.KDServiceFx.WebContext, Kingdee.BOS.ServiceFacade.KDServiceFx.RequestExtractor)
00000076dbf7db30 00007ffdac1a373e *** WARNING: Unable to verify checksum for System.Web.ni.dll
System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
00000076dbf7dbc0 00007ffdac1633fb System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
00000076dbf7dc10 00007ffdac178220 System.Web.HttpApplication+PipelineStepManager.ResumeSteps(System.Exception)
00000076dbf7dd70 00007ffdac163f79 System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext, System.AsyncCallback)
00000076dbf7ddc0 00007ffdac1766c3 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)
00000076dbf7de40 00007ffdac165398 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000076dbf7e000 00007ffdac164f63 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000076dbf7e040 00007ffdac8646ba DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
00000076dbf7e8b0 00007ffdbb4f21fe [InlinedCallFrame: 00000076dbf7e8b0] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000076dbf7e8b0 00007ffdac1d2dde [InlinedCallFrame: 00000076dbf7e8b0] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000076dbf7e880 00007ffdac1d2dde DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000076dbf7e940 00007ffdac16556f System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000076dbf7eb00 00007ffdac164f63 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000076dbf7eb40 00007ffdac8646ba DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
00000076dbf7ed18 00007ffdbb4f2453 [ContextTransitionFrame: 00000076dbf7ed18]
通過仔細比對發現這麼一條Kingdee.BOS.App.Core.MainConsole.MainConsoleServer.GetMenuArrayForCache(Kingdee.BOS.Context)
呼叫堆疊。從方法命名來看,像是用來獲取選單陣列並快取。結合前後堆疊的聯絡,我們可以大致得出這樣一個線索:使用者使用WebApi登入後會快取一份獨立的選單供使用者使用。
有了程式碼堆疊,接下來知道怎麼幹了吧?當然是核實原始碼確定問題啊。
4. 分析原始碼驗證問題
Kingdee.BOS.App.Core.MainConsole.MainConsoleServer.GetMenuArrayForCache(Kingdee.BOS.Context)
方法原始碼如下:
我們發現它是用的UserToken
來快取使用者選單。看到Token
,你可能就會條件反射的想到其生命週期。是的,聰明賢惠如你,Token是有生命週期的。也就意味著Token過期後,下次登入還會再次快取一份選單。你可能會問Token過期後沒有去清對應的選單快取嗎?是的,並沒有。
嚴謹的你,可能又會問Token多久過期?20mins。你眼珠子一轉,接著問,滿打滿算,一個使用者1個小時也就申請3次Token,24小時,也就申請72個Token,一個選單快取也就頂多1K,所以一個使用者一天也就最多佔用72K。你的網站得有多少併發,才能被這麼多選單快取撐爆啊?!
Good Question!!!
是的,客戶的應用場景的併發也就頂多幾百而已。那到底是什麼導致如此多的選單快取呢?
原因是,客戶的第三方客戶端使用WebApi與我們的系統對接。而每次呼叫WebApi時都會先去呼叫登入介面,但卻未儲存會話資訊。也就是說,客戶第三方客戶端每次的WebApi呼叫都會產生一個新的Token。那如果有成千上萬的WebApi請求,也就意味著成千上萬的選單快取啊。
好了,點到為止。至此,已經基本定位到問題的根源了。
5. 最後
也許很多同學沒有接觸過WinDbg,覺得其是一個複雜的工具。其實通過本文的案例講解,其無非是通過一系列常見的命令來進行問題跟蹤來定位問題。
最後來簡單總結下,Windbg分析問題的步驟:
- 建立完整Dump檔案
- Windbg載入Dump檔案
- 根據不同問題型別,使用相關的命令進行分析
- 耐心分析,抽絲剝繭
- 邊分析邊猜測邊驗證
- 結合原始碼驗證猜想
- 修復驗證
相關推薦
Windbg分析高記憶體佔用問題
1. 問題簡介 最近產品釋出大版本補丁更新,一商超客戶升級後,反饋系統經常奔潰,導致超市的收銀系統無法正常收銀,現場排隊付款的顧客更是抱怨聲聲。為了緩解現場的情況, 客戶都是手動回收IIS應用程式池才能解決。 這樣的後果是很嚴重的,接到反饋,第一時間想到的是加記憶體吧,這樣最快。但是客戶從8G-->
Java線上應用故障排查之二:高記憶體佔用
搞Java開發的,經常會碰到下面兩種異常: 1、java.lang.OutOfMemoryError: PermGen space 2、java.lang.OutOfMemoryError: Java heap space 要詳細解釋這兩種異常,需要簡單重提下J
linux 程序記憶體佔用高分析
通過free命令可以檢視系統記憶體使用情況: free -m total used free shared buff/cache available Mem: 79
JAVA程序佔用高記憶體原因分析與優化方法
首先看一下一個java程序的jmap輸出: 程式碼如下: [[email protected] ~]$ jmap -heap 837 Attaching to process ID 837, please wait... Debugger attached suc
利用windbg分析崩潰,控制代碼洩漏,死鎖,CPU高,記憶體洩漏
Windbg的一些簡單使用命令 一、崩潰 1、 輸入.ecxr;kbn得到崩潰的堆疊 其中原始碼如下 2、 檢視堆疊和原始碼,發現第0幀導致崩潰,程式碼也是原生代碼 輸入.frame 0,切到第0幀如下 3、 輸入 dv 檢視當前幀的一些變數資訊
unity優化《二》--Texture圖片空間和記憶體佔用分析
打包多種型別的專案,空專案和10張放在Resources資料夾中的圖為比較案例。以下是比較資料。 IPHONE: 1.空專案----空間佔用量42.3MB----IPA大小10MB 2.10張1200*520無壓縮Texure 單張圖佔用量2.8MB----空間佔用量70.2MB
Sublime Text 3 CPU佔用率過高 && WebStorm記憶體佔用過高
用Sublime Text 3或WebStorm進行前端開發時,遇到了同樣的問題:當專案檔案比較多或檔案比較大時,CPU佔用率或記憶體佔用持續比較高,後來經查閱發現是index files導致的,可以理解為:Sublime Text 3或WebStorm需要不斷重新整理檔案索引,不斷將專案檔案從硬碟中讀到
記憶體佔用過高,快取不釋放導致宕機處理方案
故障現象: 1、某分行部署的某臺伺服器記憶體佔用過高,導致宕機; 2、程式碼層面檢查暫未發現問題,伺服器硬重啟持續一段時間後(3-5天)再次佔滿。 發現問題: 趕往現場後進行檢查,當時是一切正常的,今有DB2程序佔用18%,在正常範圍內; 在crontab 中發現有兩個指
JVM記憶體佔用情況深入分析,分分鐘解開你的疑惑
很多同學都問過這個問題,為什麼我的Xmx設定4g,但是TOP命令查詢RES卻佔用5G,6G,甚至10G。這個正常嗎?也可以說正常,也可以說不正常,怎麼判斷?筆者今天就要為你解答這個問題,叫你如何分析JVM佔用的記憶體都分配到了哪裡,哪些地方合理,哪些地方異常。 記憶體分佈 首先
Lua資料結構和記憶體佔用分析
String又細分為短字串LUA_TSHRSTR和長字串LUA_TLNGSTR兩種,預設長度小於40的為LUA_TSHRSTR,使用全域性stringtable進行管理。即所有短字串都在stringtable中存放,相同字串只會有一份實際資料拷貝,每份相同的TString物件只是存放一個hash值,用來索
線上故障排查-記憶體佔用高
這篇主要分析高記憶體佔用故障的排查。 搞Java開發的,經常會碰到下面兩種異常: 1、java.lang.OutOfMemoryError: PermGen space 2、java.lang.OutOfMemoryError: Java heap space 要詳細
Spring cloud開發記憶體佔用過高解決方法
https://blog.csdn.net/wanhuiguizong/article/details/79289986 版權宣告:本文為博主原創文章,轉載請宣告文章來源和原文連結。 https://blog.csdn.net/wanhuiguizong/article/details/79
分析並優化 Android 應用記憶體佔用
視訊觀看筆記,如需轉載,請註明出處 演講人介紹 Rechard Uhler,Android Runtime 開發工程師。為便於寫作,筆者將以第一人稱視角對視訊內容進行概述。 視訊地址 1. 前言 想要進行記憶體優化,就必須對 Android 記憶體管理機制有比較深入的瞭解,這樣
Unity3D–Texture圖片空間和記憶體佔用分析
Texture圖片空間和記憶體佔用分析。由於U3D並沒有很好的詮釋對於圖片的處理方式,所以很多人一直對於圖集的大小和記憶體的佔用情況都不瞭解。在此對於U3D的圖片問題做一個實際資料的分析。此前的專案都會存在這樣或者那樣的打包後包大小與記憶體佔用情況的問題,所以這次所以徹徹底底得分析下U3D對於Texture
解決Linux buffer/cache記憶體佔用過高的辦法
-------原文地址 https://www.cnblogs.com/rocky-AGE-24/p/7629500.html --------本文只是搬運 在Linux系統中,我們經常用free命令來檢視系統記憶體的使用狀態。在一個RHEL6的系統上,fr
WINDOWS2008快取設定工具,解決系統執行久了因系統快取造成實體記憶體佔用高僵死的問題
宣告: 造成伺服器卡死的原因是因為虛擬記憶體設定過低,請大家設定虛擬記憶體時不能小於實體記憶體. 比如實體記憶體8G,虛擬記憶體不能低於8G,最好是系統預設的實體記憶體的1.5倍.即12G. 浪費點硬碟空間也沒辦法了. . 看到有朋友也遇到我們之前一樣的問題。http://
Linux中buff/cache記憶體佔用過高解決辦法
如何回收cache? Linux核心會在記憶體將要耗盡的時候,觸發記憶體回收的工作,以便釋放出記憶體給急需記憶體的程序使用。一般情況下,這個操作中主要的記憶體釋放都來自於對buffer/cache的釋放。尤其是被使用更多的cache空間。既然它主要用來做快
專案中Map端記憶體佔用的分析
最近在專案中開展重構活動,對Map端記憶體儘量要省一些,當前的系統中Map端記憶體最高佔用大概3G左右(設定成2G時會導致Java Heap OOM)。雖然個人覺得佔用不算多,但是顯然這樣的結果想要試圖去說服一些對記憶體佔用非常挑剔的C++程式設計師們理由還是不夠,於是便通過一定的方式對記憶體的佔用進行了
Linux中Cache記憶體佔用過高解決辦法
在Linux系統中,我們經常用free命令來檢視系統記憶體的使用狀態。在一個RHEL6的系統上,free命令的顯示內容大概是這樣一個狀態: 這裡的預設顯示單位是kb,我的伺服器是128G記憶體,所以數字顯得比較大。這個命令幾乎是每一個使用過Linux的人必會的命令,但越是這樣的命令,似乎真正明白的人越少(
正確理解Linux記憶體佔用過高的問題
最近有個月經問題,老有人問為何開機後,還沒有其他服務,mem就被用完了?是不是記憶體洩露?是否要重啟服務?只能說不要看現象,要看本質才能找到問題的根源。往往給出這樣的結果,懷疑記憶體用了90%:Mem: 4146788k total, 3825536k used, 3212