

高負載 .NET Logging 議題與 NLog 極端效能調校
source link: https://blog.darkthread.net/blog/high-capacity-dotnet-logging-survey/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

跟同事討論到高負載 .NET Logging 議題。某程式有巨量 Log 寫入需求,執行幾小時 Log 量可達數 GB,甚至懷疑寫 Log 可能成為效率瓶頸之一,程式目前使用 log4net,考是是否應更換成其他 Log 程式庫?如果要換,有哪些選擇?
早年用過 log4net,複雜的 XML 設定檔常讓我吐血,直到發現 NLog,二話不說立刻跳槽沿用至今,沒想過要換也就沒再留意其他 Log 程式庫,趁此機會做點功課。
把研究議題訂為「高負載 .NET Logging 解決方案評估」,如前述專案需求,以效能為首要考量。網路上討論較多的 .NET Log 程式庫有以下幾種:
整理爬文心得如下:
Benchmarking 5 popular .NET logging libraries
2016 年的評測,比較 log4net、ELMAH、NLog、MS Enterprise Library、NSpring,結論:NLog 最快,效能是 log4net 的五倍,第二名是 MS Enterprise Library,NSpring 第三,ELMAH 殿後,效能只有 NLog 的 1/10。
在設定及便捷性方面,NLog、log4net 較佳,NSpring 較麻煩,Enterprise Library 不辱其「企業級」之名,一整個複雜。ELMAH 只能搭配 ASP.NET 應用範圍較窄,每個事件以 XML 保存推測是效能較差原因。
.NET 低延遲 Log 測試
作者設計了一套評測程式,比較了 NLog, log4net, log4j2, 但偏重對 log4net 的設定調校。
Serilog vs NLog Benchmarks
Serilog 是近年掘起的 .NET Log 程式庫,標榜 Log 以結構化格式(JSON)儲存,有利事後查詢整理。作者沿用上一則文章的測試方法,在這份評測中,Serilog 的效能為 NLog 的兩倍。但有網友留言提到測試所用的 Liblog 抽象架構及設定差異嚴重影響評測結果,NLog 數據有大幅修正空間,細節留待後面說明。
NLog BufferingWrapper
NLog 有個 BufferingWrapper,允許累積一定筆數再批次寫入儲存媒體或傳送,可降低頻繁開啟關閉檔案或連線的成本,或減少通知頻率過高的困擾。(註:NLog 另外也有 AsyncWrapper 支援非同步寫入,意指程式不需停下來等 Log 寫完,可避免為了寫 Log 拖累核心作業執行。)
NLog FileTarget 效能參數
FileTarget 有多個參數可用於提高效能:
- keepFileOpen
設為 true 可保持檔案開啟,取代每次寫 Log 就開啟關閉一次,如此可大幅提高效能,缺點是會鎖定檔案,建議配合 openFileCacheTimeout = 30 服用,預設為 false。 - concurrentWrites
當 keepFileOpen = true 時允許同主機上其他 Process 也寫到同一 Log 檔(背後有黑魔法),若只有單一 Process 會寫入該 Log 檔,建議設 false 提高效率。 - openFileCacheTimeout
檔案保持開啟的時限,超過一段時間未使用便將檔案關閉,設為 -1 表永不關閉。預設為 -1。 - openFileCacheSize
當單一 File Target 寫入多個檔案(例如:依 Level 區分多個檔案),保持開啟檔案數目的上限(超過此數量時關閉最久沒使用的檔案),加大有助提升效能(但勿超過 10-15,以免佔用系統資源)。預設為 5。 - optimizeBufferReuse
寫入 Log 訊息時重複使用緩衝記憶體,預設為 true。(NLog 4.4.2+) - networkWrites
網路上如有其他 Process 要同時寫入 Log 檔,設為 true 可防止檔案持續開啟,預設為 false。 - concurrentWriteAttemptDelay
寫入檔案失敗再次嘗試前的等待亳秒(ms)數,實際應用時取 0 到此延遲數字的亂數值,例如:設為 10 表示取 0-10ms 間的亂數。若再次失敗,延遲時間乘以 2 取 0-20ms 亂數,再失敗再取 0 - 40ms 亂數,以此類推。預設為 1。 - concurrentWriteAttempts
寫入失敗嘗試次數上限,超過次數則丟棄訊息。預設為 10。 - cleanupFileName
寫入檔案前要檢查檔案是否合法(依 OS 有別),若遇大量寫入時此檢查將消耗資源,設為 false 可提升效能。預設為 true。(NLog 4.2.3+) - bufferSize
緩衝區大小,預設值為 32768 - autoFlush
是否每次寫 Log 都將緩衝區內容寫入檔案,設為 false 可提升效能(需搭配 openFileFlushTimeout),預設為 true。 - openFileFlushTimeout
當 autoFlush = false 時,設定每隔幾秒強制寫入檔案清空緩衝區,預設為 0。
NLog FileTarget 效能最佳化
Github 看到一則不錯的討論,參考其中建議:
var fileTarget = new FileTarget
{
Name = "FileTarget",
FileName = "Log.txt",
KeepFileOpen = true,
ConcurrentWrites = false,
AutoFlush = false,
OpenFileFlushTimeout = 1,
};
keepFileOpen 設 true,concurrentWrites 設 false,autoFlush 設 false,openFileFlushTimeout 設 1 秒。在此設定下,NLog 之效能數字優於 Serilog。
另外,BufferingTargetWrapper 主要用於減少觸發外部通知管道次數(例如:第三方通訊軟體的 WebAPI、Email... 等),不利於檔案最大輸出,拼效能時應移除。 經過上述調整,NLog 效能明顯勝過 Serilog。(首頁的數據已提 PR 等待更新)
NLog vs log4net vs Serilog: Compare .NET Logging Frameworks
這是另一篇 NLog、log4net 與 Serilog 評比,聚焦於使用面而非效能面。
log4net 設定檔又臭又長眾所皆知,且更新緩慢(已 18 月未更新)已顯老態。 NLog 專案相對有活力,仍在持續改進,最新版加入結構化 Log 並支援 .NET Standard。(作者提到一項缺點是 NLog 出錯訊息易被忽略,此點可修改設定克服)。
Serilog 很新,2013 才誕生,強調 Log 資料 JSON 化,方便事後查詢、解析。由於年輕,Serilog 的設定語法更貼近未來趨勢,與 .NET Core 的語法很像,
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logfile.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
已走進新時代的開發者應會感覺格外親切,但對老人來說,則需要一點時間學習適應。
綜合以上討論,結論如下:
- log4net、NLog 及 Serilog 是 .NET 寫 Log 最主流的三項選擇。
- log4net 更新腳步慢,可怕的 XML 設定檔是其致命傷,繼續放生。
- 回到效能議題,依目前評測數據,NLog 與 Serilog 不相上下,但如何調校很重要,沒調好數字可差 N 倍。
- NLog 有一些重要效能參數 keepFileOpen、concurrentWrites、autoFlush、openFileFlushTimeout,避用 BufferingWrapper,是大幅提升寫 Log 效能的關鍵。
- Serilog 更貼新新一代 .NET 程式撰寫風格,強調結構化 Log 及高效能,貌似明日之星。(註:新版 NLog 也已支援結構化 Log,至於效能評比數據,若經妥善調校,NLog 與 Serilog 並無壓倒性差異)
- 個人觀點,手上專案仍會選擇 NLog,理由是其成熟度、使用簡便、彈性大及高效能。但會觀注 Serilog,未來伺機嘗試轉換。
Recommend
-
32
Logging information in .NET, or really in any production application, is invaluable. In many cases, developers don’t have direct access to the production environment to debug issues. Good quality logs are the difference b...
-
9
NLog 是一个开源的轻量级日志框架,提供了丰富的日志路由和管理功能,同时 NLog 也是非常容易的去配置和扩展,其实在之前的文章中我已经讨论过了 Nlog,在这篇我准备继续和大家讨论一下 NLog 的更多高级功能。 接下来看看如何通过...
-
10
免 NLog.config 設定 Log 路徑 2021-01-23 07:11 AM
-
13
背景 NLog可以将日志输出到不同的媒介上,邮件是其中一个,通过邮件可以让我们第一时间收到信息。使用SMTP协议通过电子邮件发送日志消息。与FallbackGroup Target很好地结合在一起,以创建具有多个SMTP主机的后备。
-
3
MongoDB 效能調校紀錄 最近剛好在實作 Prometheus + Grafana 的時候,對 MongoDB 做了容器 CPU 使用率 (container_cpu_usage_seconds_total) 的監控,Metrics...
-
5
Configuring NLog by Program advertisements I have a working configure of NLog. I use NLog.config <nlog xmlns="http://www.nlog-pro...
-
6
[Rancher 系列文] - Project, IaC 以及相關議題 Posted on 2021-11-30 Views: 6 Rancher 系列文第六篇,探討創建 k8s 的方式 前幾篇文章探討了如何透過 Rancher 操作與管理 Kubernetes 叢集,...
-
12
在 ZFS 上跑 PostgreSQL 的調校 在「Everything I've seen on optimizing Postgres on ZFS」這邊看到如果要在
-
7
async/await 效果與 ThreadPool 調校-黑暗執行緒 陸續看過 .NET ThreadPool 執行緒數量增減模式,也見識了
-
8
ASP.NET 偵錯模式的資安議題 2023-08-02 10:53 PM 0
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK