JSON日誌文件

今天想聊個日誌系統相關的話題。

在我們的項目中日誌文件有兩種,第一種是程序輸出的錯誤信息、警告信息、調試信息等,第二種是遊戲伺服器和資料庫之間同步的事務日誌。前者我稱之為系統日誌,後者我稱之為事務日誌。

系統日誌在我們以往的項目中都是用一個沒有格式限制的日誌模塊來記錄,唯一形成規格的就只有日誌的時間信息和類型信息。

事務日誌我們為了提高寫入效率和減小文件體積,用的是自定義的二進位文件格式。

無格式規範的系統日誌不容易做信息收集,比如要收集某段時間某種類型的錯誤的發生頻率,或者是某個模塊的錯誤率等,都會是很麻煩的事情。

而事務日誌還算好一點,因為它是結構化的,我們做了一個叫做log2sql的工具,可以從同步日誌中提取數據來生成redo或者undo用的SQL,也可以用lua腳本對日誌中記錄的變化進行分析,比如計算某個玩家的體力值變化,看是否存在利用漏洞的行為。但是由於使用的是自定義的二進位文件格式,所以周邊分析工具的開發很繁瑣,和第三方工具的配合使用也很不友好。

要解決目前遇到的這些問題,我想到的是JSON,因為目前絕大多數常用語言都可以解析JSON數據,所以周邊分析工具的開發以及第三方工具的配合會變得方便很多。

舉個例子,在引入JSON格式的日誌之後,我很快就用PHP做了一個日誌查看頁面,因為信息是結構化的,這個查看頁面要做過濾篩選或者特殊顯示就變得方便許多,不是先前做不到,而是做起來很繁瑣。

但是JSON日誌比起二進位文件格式來說,有個明顯的問題是JSON導致的文件體積膨脹。

所以,我在做了基礎的JSON日誌記錄之後,又做了幾組數據壓縮相關的測試。

分別測試了以下內容:

    1. 二進位數據格式的體積
    2. JSON序列化但不壓縮數據時候的文件體積
    3. gzip最低壓縮比壓縮後的文件體積
    4. gzip中等壓縮比壓縮後的文件體積
    5. gzip最高壓縮比壓縮後的文件體積
    6. snappy壓縮後的文件體積
    7. JSON序列化但不壓縮數據時的數據流量
    8. gzip最低壓縮比時的數據流量
    9. gzip中等壓縮比時的數據流量
    10. gzip最高壓縮比時的數據流量
    11. snappy壓縮時的數據流量

測試結果如圖:

從實驗的結果看,數據流量的瓶頸在於JSON的序列化過程而數據壓縮演算法足夠高效,不會在這個應用場景下成為瓶頸。同時可以看到gzip壓縮後的文件體積遠小於不壓縮的JSON文件。

還有個比較意外的情況是gzip壓縮後的體積小於不壓縮的二進位數據的體積。

所以可以得出一個結論,對JSON日誌文件寫入使用gzip流壓縮是非常划算的。

上述實驗的代碼:go-labs/labs29 at master · idada/go-labs · GitHub

所以我就給JSON日誌模塊加上了gzip壓縮功能。

但還有個疑問,使用gzip壓縮的時候如果文件沒有正常關閉,是否會導致嚴重的數據損壞呢?經過測試,答案是不會。

與JSON直接寫入一樣,如果進程異常退出導致部分信息沒有寫入,那麼損失的就是最後沒有完整寫入的這部分數據,並不會導致整個文件不可用。

這裡有一個簡單的PHP腳本用來做這個測試:

<?phpnif (($file = gzopen($argv[1], r)) !== false) {ntwhile (!gzeof($file)) {ntt$line = gzgets($file);nttif ($line === false)ntttbreak;nttecho $line;nttecho "n";nt}ntgzclose($file);n} else {ntecho "open file failedn";n}n?>n

目前市面上其實有一些日誌管理工具和日誌分析工具,大多都是分散式的,還有專門用JSON格式的。

在跟身邊的一些朋友分享最近做JSON日誌的這個事情的時候,大家有疑問為什麼不直接上這類型的系統。

我的想法其實很簡單,在看不清楚狀況的時候,我不想引入第三方系統,也不想對第三方系統有強依賴。

這是一個投產比問題,引入一個分散式日誌系統的代價是強依賴性,運維複雜度的提升,運營成本的提升。

而寫JSON文件是一件很簡單的事情,我們可以用很低的成本做好它,同時它不像二進位文件那樣阻斷跟第三方系統的配合可能性,如果要上第三方系統的時候,可以做個程序抓取和提交到系統里,不用讓遊戲和日誌系統間有直接的耦合。

目前我們真的需要一套龐大的日誌系統來支撐相關業務嗎?在遊戲伺服器方面我並沒有明顯看到這樣的需求。

先前的二進位同步日誌文件其實已經能滿足一些基本的數據挖掘需求,而JSON文件又進一步提高了這方面的能力,再加上遊戲伺服器部署結構天生的分散式,以及運維備份方案和磁碟陣列的使用帶來的高可用性。

在這樣的情況下引入分散式的日誌系統所投入的成本所獲得的回報似乎並不高,換個方式說就是投產比低。

所以在還沒有看清楚情況(如何提高投產比)的時候,我寧可用最低的成本做最有效的改進,但同時也為以後可能的架構升級留一條後路。

我們項目里用的JSON日誌模塊和系統日誌模塊都已經放到公司的github。

JSON日誌模塊的代碼倉庫:funny/jsonlog · GitHub

系統日誌模塊的代碼倉庫:funny/log · GitHub

系統日誌模塊只是基於JSON日誌模塊再封裝了一層系統日誌常用的API。而事務日誌由於項目耦合度太高,就不方便開源了,開發的時候也是基於JSON日誌模塊再封裝了一層。

好了,今天關於JSON日誌的話題就到這裡,謝謝閱讀,求點贊 :)


推薦閱讀:

ELK 實時日誌分析平台環境搭建
日誌分析的模式發現功能實現(3)
可能是最好用的日誌分析工具
有哪些基於ELK的億級實時日誌分析平台實踐的案例?
有用過Splunk的嗎,大家都用Splunk做什麼?

TAG:Go语言 | JSON | 日志分析 | 服务端开发 | 架构设计 |