天天看點

三步快速解決dll沖突問題

最近在推廣應用我們的分布式服務網關(Web Api):業務組大部分對外的業務邏輯以HSF服務或者自定義擴充插件的方式,注冊并釋出到分布式服務網關中,統一對外提供WebApi服務。臨時介紹下我們的分布式服務網關:

1. 一鍵注冊、釋出WebApi服務,

2. 統一管理釋出WebApi服務,實作WebApi的服務化治理

3. 內建安全認證、加解密、監控、日志等Aspect

4. 流量安全控制:流控

5. 橫向伸縮、彈性擴充,支援大規模并發 

6. 簡化WebApi開發,提升開發效率,減少重複開發工作

在實際的開發應用中,業務邏輯dll要注冊、釋出到分布式服務網關中,例如參數類型、自定義擴充插件等。

每次業務的變更,都需要重新釋出服務,例如實體類的注解(屬性标簽)發生變化,重新釋出服務,分布式服務網關偵測到變化,重新加載。

同時,各個業務子產品之間存在SPI層接口、實體類的依賴,例如:A中依賴B.Spi.dll, B釋出了最新的B.Spi.dll, A未釋出,這樣會産生一個問題:

一個AppDomain中隻能加載一個B.Spi.dll,如果先通路A服務,那麼舊版本的B.Spi.dll就會先加載到AppDomain,此時,通路B服務時,就會出現dll沖突問題:

例如:

{"ErrorInfo":"資料序列化錯誤:程式集“***.Module.CarMdelAnalyse.SPI, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=null”中的類型“***.Module.CarMdelAnalyse.SPI.CarModelAnalyseResult”未标記為可序列化。r\rn   
在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)\r\n   
在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)\r\n   
在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()\r\n   
在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector,
 StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, 
SerializationBinder binder)\r\n   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo,
 NameInfo memberNameInfo, NameInfo typeNameInfo)\r\n   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph,
 Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)\r\n   
在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers,
 Boolean fCheck)\r\n   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)\r\n  
      

類似的錯誤還有:

 未能加載檔案或程式集“***.dll”或它的某一個依賴項

運作時如何快速定位到dll 沖突的根本原因,找到到底加載的dll是在GAC中、還是Bin中、還是指定目錄中的dll?

有經驗的老司機,分享給大家一個三步法,屢試不爽!!!

1. 找到程式主程序,右鍵:Create Dump File,如果IIS站點:指定應用程式池下的w3wp程序,如果自己的服務程序,直接找程序即可

2. 安裝指定版本的Windbg(X86\X64), Ctrl+D 加載第一步抓的Dump檔案,.loadby sos clr  -> !dumpdomain

3. 找到相關的dll檔案路徑,ILSpy,反編譯定位問題,解決。

show:

1. 抓dump:通過上面的錯誤堆棧,我們定位到w3wp.exe,  右鍵建立轉儲檔案

三步快速解決dll沖突問題

2. 安裝Windbg, 請根據程式的32/64版本下載下傳安裝不同的Windbg,我們用的64位,是以用的Windbg是X64版本的。打開windbg,Ctrl+D, 加載剛才抓的dump檔案

三步快速解決dll沖突問題

依次輸入指令:.loadby sos clr  -> !dumpdomain

三步快速解決dll沖突問題
三步快速解決dll沖突問題

得到domain資訊輸出:

以ServiceStack.Redis.dll這個dll為例,可以找到在哪個路徑下加載的dll:類似的找業務相關的dll即可:

三步快速解決dll沖突問題

3. 找到AppDomain加載的dll,拷貝,ILSpy:

三步快速解決dll沖突問題

windbg的确在記憶體鏡像分析時是一個利器,贊一個!

周國慶

2017/4/23