Windbg分析高內存佔用問題

1. 問題簡介

最近產品發佈大版本補丁更新,一商超客戶升級後,反饋系統常常奔潰,致使超市的收銀系統沒法正常收銀,現場排隊付款的顧客更是抱怨聲聲。爲了緩解現場的狀況, 客戶都是手動回收IIS應用程序池才能解決。 現場排隊狀況數組

這樣的後果是很嚴重的,接到反饋,第一時間想到的是加內存吧,這樣最快。可是客戶從8G-->16G-->32G,只是延長了每次奔潰的時間,可是並無解決系統卡頓的問題。到這裏,也基本猜想了問題所在了,確定是什麼東西一直在吃內存且得不到釋放。這種問題,也就只能打Dump分析了。緩存

2. 打Dump

遠程客戶應用服務器,32G內存佔用已經消耗了78%,而現場已經反饋收銀系統接近奔潰了,要求先強制回收內存。反正也要奔潰了,先打Dump再說吧。 (PS:打Dump會掛起進程,致使應用沒法響應!而打Dump的耗時,也是根據當時進程的內存佔用有關,內存佔用越大,耗時越久。) 打開任務管理器,選擇對應的IIS進程,右鍵建立轉儲文件(Dump)。 打Dump服務器

結果,Dump文件是生成的,結果當分析的時候,發現Windbg提示Dump無效。說明Dump文件建立的有問題。觀察任務管理器,發現內存佔用一下就降下來了,原來是以前的進程直接奔潰了,重啓了一個W3WP進程。併發

既然直接從任務管理器沒法建立,就使用第三方工具收集Dump吧。通過Goggle,找到一款很好用的Dump收集工具ProcDump,是一個命令行應用,其主要用途是監視應用程序的CPU或內存峯值並在峯值期間生成Dump。app

由於是高內存佔用問題,咱們使用如下命令來抓取dump: (PS:可使用進程名稱,也可使用進程ID來指定要建立Dump的進程。當有多個相同名稱的進程時,必須使用進程ID來指定!)工具

procdump w3wp -m 20480 -o D:\Dumps (當內存超過20G時抓取一個w3wp進程的MiniDump)學習

上面就是我踩得第一個坑,由於默認抓取的是MiniDump,很快就抓下來,文件也很小,正在我得意的時候,Windbg加載Dump分析的時候,發現包含的信息不多,根本沒法進行進一步的分析。網站

調整建立Dump的命令,添加-ma參數便可建立完整Dump。spa

procdump w3wp -ma -m 20480 -o D:\Dumps (當內存超過20G時抓取一個w3wp進程的完整Dump)命令行

結果再一次,當內存佔用到達20G,佔比80%的時候,Dump再次建立失敗,提示:Procdump Error writing dump file。再一次感受到絕望。不過至少有錯誤提示,Google一把,果真存在天涯淪落人。Procdump Error writing dump file: 0x80070005 Error 0x80070005 (-2147024891): Access is denied。大體的意思是說,當90S內Dump文件沒有成功建立的話(也就意外這w3wp進程被掛起了90s),IIS檢測到w3wp進程掛起超過90s沒有響應就會終止進程,重現建立一個新的進程。好嘛,真是到處是坑。

這個坑,也讓我開始真正停下來思考問題。**羅馬不是一日建成的,內存也不是一下撐爆的。**我幹嗎死腦筋非要到內存佔用超過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命令查看當前全部託管類型的統計信息。從輸出的結果來看:

  1. 其中佔用內存最多當屬System.String類型,接近4G的大小(是否是很吃驚?!)。
  2. 其次System.Object[]類型佔有1.3G大小。
  3. 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

從上面的輸出能夠發現:

  1. 單個System.String類型最大佔用2M以上。
  2. 超過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).

從以上輸出能夠看出:

  1. 該String類型被一個Hashset所持有。
  2. 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.

從輸出結果來看:

  1. 滿屏都是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

從輸出能夠看出:

  1. JSONArray實質是System.Object[]類型。
  2. 對應的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)方法源代碼以下: GetMenuArrayForCache

咱們發現它是用的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分析問題的步驟:

  1. 建立完整Dump文件
  2. Windbg加載Dump文件
  3. 根據不一樣問題類型,使用相關的命令進行分析
  4. 耐心分析,抽絲剝繭
  5. 邊分析邊猜想邊驗證
  6. 結合源碼驗證猜測
  7. 修復驗證
相關文章
相關標籤/搜索