在.NET Core 中收集數據的幾種方式
APM是一種應用性能監控工具,可以幫助理解系統行為, 用於分析性能問題的工具,以便發生故障的時候,能夠快速定位和解決問題, 通過匯聚業務系統各處理環節的實時數據,分析業務系統各事務處理的交易路徑和處理時間,實現對應用的全鏈路性能監測。
組成結構
- 探針(Agent):負責在客戶端程序運行時搜索服務調用鏈路信息,發送給收集器
- 收集器(Collector):負責將數據格式化,保存到存儲器
- 存儲器(Storage):保存程序數據
- UI界面(Dashboard):多維度展示數據
本文會主要針對 探針 (Agent), 分享下在.NET 程序中收集程序數據的幾種方式,如果需要自研 APM 系統或者收集數據來進行系統分析,希望能可以給大家一些幫助,以下幾種方式,大家可以針對自己的場景去選擇,我們的目的只是收集數據。
手動埋點
手動埋點比較簡單,我們需要在一些操作前後可以手動包裹我們的埋點代碼,比如 Http,RPC,DB, MQ 等調用,非常靈活,可以在任意的地方添加我們的埋點信息,然後匯總數據,按批發送,缺點是對程序的侵入性較高,不太優雅。
Middleware 中間件 & 過濾器 Filter
得益於 .NET Core 優秀的框架設計, 它具有一個極具擴展性的請求處理管道,我們可以通過這個管道的定製來滿足各種場景下的HTTP處理需求。ASP. NET Core應用的很多特性,比如路由、認證、會話、緩存等,也同時定製消息處理管道來實現的,所以我們需要編寫自定義的攔截中間件 InterceptMiddleware,獲取到請求上下文 HttpContext, 來攔截所有的Http請求收集數據,注意這裡中間件的位置要放到 UseEndpoints() 的上面,同樣可以藉助 過濾器 AcitonFilter,來完成同樣的效果, 但是這種方式可獲取的信息有限,只能攔截到 Http 請求的一些信息
DiagnosticSource
實現:
SkyApm-dotnet //github.com/SkyAPM/SkyAPM-dotnet
HttpReports APM //github.com/dotnetcore/HttpReports
診斷 DiagnosticSource 我們不經常用,可能都有點陌生,但是它的功能是非常強大的,它本身是一個基於發佈訂閱模式的工作模式,我們可以異步的去收集信息,比如 中間件的進入和退出,HttpClient 調用的開始和結束,並且有很多第三方的庫都支持了 DiagnosticSource,這也是微軟目前推薦的方式,在改動極少代碼的情況下,採集到豐富的運行數據。
引用 AOP
額,面向切面編程,這個需要在我們的 .NET 程序中引用 AOP 框架,如果是內部系統的話,我覺的還是可以接受的,常見的框架 AspectCore, Castle.Core, 通過 AOP 的特性,我們可以攔截需要獲取數據的方法,如果你在項目中,普遍使用依賴注入的話,可以達到方法級別的監控,獲取到的信息非常可觀,另外需要注意的是,獲取的信息越詳細,數據量也越大,是全量採集數據還是抽樣採集也是要考慮的點
EWT(Event Tracing for Windows)
ETW是Event Tracing for Windows的簡稱,它是Windows提供的原生的事件跟蹤日誌系統。由於採用內核(Kernel)層面的緩衝和日誌記錄機制,所以ETW提供了一種非常高效的事件跟蹤日誌解決方案。
這個庫我還沒怎麼用過,生而為人,我很抱歉 〒▽〒
Mono.Cecil
Mono.Cecil:一個可加載並瀏覽現有程序集並進行動態修改並保存的.NET框架, Mono Cecil十分強大,可以靜態注入程序集(注入後生成新的dll程序集)和動態注入程序集(注入後不改變目標程序集,只在運行時改變程序集行為,騰訊開源的Unity熱更解決方案xLua有一個非常吸引人的特性就是Hotfix,其原理是使用Mono.Cecil庫對進行C#層編譯出來的dll程序集進行IL代碼注入。
CLR Profiling API
實現
聽雲APM(商業)OneAPM (商業)Datadog (商業)
//docs.microsoft.com/en-us/archive/blogs/yirutang/clr-profiling-api
這個真的是一個很棒的方案,你可以看到,很多的 商業APM 系統,都採用了這種方式,因為它是一種無侵入的收集方式,CLR Profiling (分析) API 是CLR中最酷的東西之一, 分析 API 提供 CLR 中發生的各種事件和操作的相關信息, 你可以使用此信息來監視進程的內部工作情況,也可分析 .NET 應用程序的性能
支持的功能如下:
- CLR 啟動和關閉事件。
- 應用程序域創建和關閉事件。
- 程序集加載和卸載事件。
- 模塊加載和卸載事件。
- COM vtable 創建和析構事件。
- 實時 (JIT) 編譯和代碼間距調整事件。
- 類加載和卸載事件。
- 線程創建和析構事件。
- 函數入口和退出事件。
- 異常。
- 託管和非託管代碼執行之間的轉換。
- 不同運行時上下文之間的轉換。
- 有關運行時掛起的信息。
- 有關運行時內存堆和垃圾回收活動的信息。
這可能要求你掌握 C++ 和 C#, 另外需要注意的是,Profiler 是一個非託管的 DLL 庫,會在應用運行時被加載到 CLR 中並與應用處於同一進程空間下,所以 Profiler DLL 實質上是不受託管代碼的訪問控制的,還有,Profiler DLL 作為 CLR 的一個插件,其運行錯誤可能會引起 CLR 本身的崩潰,所以你必須要知道這些風險,並且足夠小心,最後祝你好運
另外
HttpReports 是針對.Net Core 開發的APM系統, 基於MIT開源協議,針對於微服務場景,感興趣的同學可以點個 Star 支持下,謝謝, 我們
Github://github.com/dotnetcore/HttpReports