PowerDotNet平台化軟體架構設計與實現系列(11):日誌平台

所有後端應用幾乎都會記錄日誌,日誌系統可以統一抽象出來提供服務。

最近被Log4j2的安全漏洞刷屏了,作為開發人員的我只能咩哈哈幾次表示日誌處理太難了,只有折騰過的人才知道這裡面的艱辛啊。

在實現PowerDotNet日誌系統之前,參考調研了Flume、ELK、Scribe和kafka的日誌解決方案,對比後最終選擇Facebook的日誌系統Scribe作為目標,實現了基於thrift協議(當然也支援http協議)無鎖且非同步的更高性能簡潔而穩定的可擴展日誌系統Power.XLogger。

本文講講PowerDotNet內置的日誌平台系統。

環境準備

1、(必須).Net Framework4.5+

2、(必須)MySQL或SqlServer或PostgreSQL或MariaDB或MongoDB或ElasticSearch

3、(必須)PowerDotNet資料庫管理平台,主要使用DBKey功能

4、(必須)PowerDotNet配置中心Power.ConfigCenter

5、(必須)PowerDotNet註冊中心Power.RegistryCenter

6、(必須)PowerDotNet基礎數據平台Power.BaseData

7、(必須)PowerDotNet快取平台Power.Cache

8、(必須)PowerDotNet消息平台Power.Message

9、(必須)PowerDotNet人員管理平台Power.HCRM,後續文章詳細介紹

一、Scribe簡介

Scribe是Facebook開源的日誌收集系統,它能夠從各種日誌源上收集日誌,存儲到一個中央存儲系統(可以是NFS,分散式文件系統等)上,以便於進行集中統計分析處理。

Scribe為日誌的「分散式收集,統一處理」提供了一個可擴展的高容錯的方案。

Scribe從各種數據源上收集數據,放到一個共享隊列上,然後push到後端的中央存儲系統上。

當中央存儲系統出現故障時,Scribe可以暫時把日誌寫到本地文件中,待中央存儲系統恢復性能後,Scribe把本地日誌續傳到中央存儲系統上。

Scribe主要包括三部分,分別為Scribe Agent, Scribe和存儲系統。

1、 Scribe Agent

Scribe Agent實際上是一個thrift client。 向Scribe發送數據的唯一方法是使用thrift client, Scribe內部定義了一個thrift介面,用戶使用該介面將數據發送給server。

2、Scribe

Scribe接收到thrift client發送過來的數據,根據配置文件,將不同topic的數據發送給不同的對象。Scribe提供了各種各樣的store,如 file, HDFS等,Scribe可將數據載入到這些store中。

3、Store

Scribe中的Store也就是我們所理解的存儲系統,當前Scribe支援非常多的Store,包括:

file(文件)

buffer(雙層存儲,一個主儲存,一個副存儲)

network(另一個Scribe伺服器)

bucket(包含多個 store,通過hash的將數據存到不同store中)

null(忽略數據)

thriftfile(寫到一個Thrift TFileTransport文件中)

multi(把數據同時存放到不同store中)

二、日誌存儲

PowerDotNet的日誌平台設計借鑒了Scribe,也支援從各種數據源上收集數據,放到一個共享隊列上,然後push或pull到後端的中央存儲系統上。

不過考慮到不同的應用場景,這個共享隊列被設計成動態可配置的日誌容器,容器可以是主流的幾種消息隊列(RabbitMQ、MSMQ、RocketMQ、Kafka等),redis,本地快取等。

當存儲系統出現故障時,PowerDotNet也會把日誌「消息」暫時(序列化)寫到本地文件中,待存儲系統恢復性能後,再把本地日誌(反序列化)續傳到中央存儲系統上。這種日誌記錄容錯思想其實比較簡單直白,非常容易理解。

PowerDotNet內置的日誌存儲媒介(也就是中央存儲系統)包括MongoDB、MySQL、MariaDB、PostgreSQL、SQLServer和ElasticSearch,也給Exceptionless和ELK預留了介面,後續開發考慮把Hive也加進去,畢竟對於日誌系統而言,大數據量處理和較為完善的分析工具鏈是極其重要的參考指標。

在創建後端應用的時候,配置中心會自動分配一個記錄日誌的DBKey,默認為PostgreSQL,但是個人在公司里碰到的更多的是使用MongoDB或者ElasticSearch或者ELK。

配置好DBKey,日誌系統自動生效。寫程式碼的時候調用現有的PowerDotNet記錄日誌方法即可。

PowerDotNet記錄日誌方法默認是全非同步收集,不會影響業務主流程。

PowerDotNet日誌組件支援敏感資訊脫敏,這也是非常常見的業務需求功能。

對比Scribe的存儲系統,PowerDotNet.XLogger做了大量裁剪。

三、日誌管理

1、獲取DBKey

因為每個應用默認都配置了一個DBKey,所以查詢應用的日誌時,需要通過DBKey間接找到存儲,最後再將查詢數據顯示出來。

考慮到由於日誌量通常都非常龐大,所以我們設計日誌系統的時候都需要考慮分片處理。

DBKey配置日誌這種方式天然就適合日誌分片存儲,在日誌發展到一定數據量級以後,不需要運維和DBA介入,直接換個DBKey或者通過DataX數據同步平台修改DBKey連接串就可以切換新的日誌存儲介質,歷史日誌如果需要,通過其他工具直接訪問,簡直不要太容易。

2、日誌查詢

日誌查詢介面自動根據應用適配DBKey找到自己的日誌記錄。

 3、調用鏈查詢

對於調用鏈路複雜冗長的介面,調用鏈查詢支援非常重要,根據個人開發運維經驗,在排查線上問題的時候,調用鏈查詢功能發揮了非常直觀高效的作用。

調用鏈支援多系統多應用的查詢,不同系統的DBKey可能不同,數據存儲在不同的資料庫中,這時候需要我們自己在記憶體中進行聚合分頁展示。

有些開源的優秀組件,如zipkin或SkyWalking+SkyApm,在你的服務中埋點相應程式碼,可以實現分散式鏈路追蹤系統。

調用鏈查詢對於排查調用異狀非常有幫助。

四、其他

對於日誌系統而言,我們幾乎不會強調ACID、CAP、BASE這些要求。日誌系統應該儘可能做到快速高效不影響主業務流程,如果在保證日誌高可用的同時,能不丟數據那是最好的結果。

Power.XLogger默認推薦各應用使用AOP方式記錄日誌,統一日誌記錄格式,當然為了便於排查問題,也需要在某些步驟埋點記錄特定日誌。

對於某些系統,日誌可能非常重要,比如支付、財務、賬戶等系統。

如果日誌是業務邏輯里非常重要的一部分,尤其關鍵環節的重要日誌,不但業務邏輯可能要用到,而且排查追蹤問題也很有用處,這種情況下,就不建議直接使用日誌平台了。

PowerDotNet對於這些日誌敏感系統,都會在自身系統里建立日誌表進行核心關鍵日誌記錄,當然也支援按需在Power.XLogger記錄日誌。

對於日誌系統的埋點操作,建議使用Power.XLogger的非同步批量處理方法,並且顯式帶上超時時間,Power.XLogger記錄日誌默認2秒超時,默認批量處理200條數據,這兩個參數可通過配置中心動態調整。

日誌隊列堆積到一定閾值(默認20萬條,可在配置中心動態配置)自動裁剪日誌,防止系統記憶體不足或其他原因導致崩潰。

參考:

//flume.apache.org

//github.com/facebookarchive/scribe

//kafka.apache.org

//www.elastic.co/cn/products/logstash

//www.elastic.co/guide/en/logstash/5.6/index.html

//www.elastic.co/cn/products/kibana

//www.elastic.co/guide/en/kibana/5.5/index.html

//www.elastic.co/cn/products/elasticsearch

//www.elastic.co/guide/en/elasticsearch/reference/5.6/index.html

//elasticsearch.cn

//www.elastic.co/cn/products/beats/filebeat

//www.elastic.co/guide/en/beats/filebeat/5.6/index.html