之家經銷商技術部日誌系統設計實現
1. 背景
之家經銷商業務迅猛發展,技術團隊日益壯大,系統的數量和複雜度快速上升,從3年前的20人到如今170人的技術團隊。 在對業務提供支持的過程當中,咱們本身面臨了很多的問題,主要痛點以下:java
- 痛點1:發現問題的時間點嚴重滯後於端用戶
之前問題反饋的路徑是:端用戶反饋給顧問,顧問找產品確認,產品找開發和測試。這條反饋路徑至關長而且低效。 通常來講,當顧問收到用戶反饋的時候,形成的影響面已經不小了,這中間還有信息流轉,溝通不順暢等問題,根本沒法 作到先於用戶發現問題。nginx
- 痛點2:開發排查問題效率低下
大量的文本和不合理的日誌記錄,不只沒有帶來效率提高,反而是一個阻礙,從幾百兆的文本日誌裏查找關鍵錯誤信息 對任何人都是一個很大的挑戰,更別說效率了。因此基本是靠回憶上線改動,而後猜想驗證,中間還有反覆的過程,對 開發來講,也是至關痛苦。git
- 痛點3: 開發對本身系統運行情況毫無把握
在之前,你若是問開發同事,大家接口的性能咋樣,平均耗時,tp99是多少,一天有多少個500錯誤,耗時大於500ms 的請求一天有多少個,開發同事只能用絕望的眼神告訴你:不知道。看到這裏,開發的同窗均可以自問一下,可否回答出 這些問題。github
沒有系統指標統計和監控,每每讓開發感受平靜的表面下暗藏各類問題,不知道何時爆發。問題反饋到開發的時候, 開發毫無準備,毫無安全感,不說疲於奔命,離從容應對還差十萬八千里吧。web
- 痛點4: 沒有日誌監控的微服務是半條腿走路
注意不是一條腿是半條腿。在咱們團隊開始微服務選型的時候就已經意識到,沒有系統全面的日誌和監控,微服務帶 來的問題不會比收益小。spring
相信這些問題,每一個開發團隊多少都會有共鳴。sql
2. 解決方案
解決這些痛點的辦法,一套好用的日誌系統是一個很天然的解決方案。以前,日誌的利用率簡直低到可怕,線上產生 大量的文本日誌,根本無人問津,要想從這些日誌裏挖掘關鍵的信息,你須要會不少高級技能和一些黑科技工具,讓不少 開發同事望而生畏。因此首先要挖掘日誌這座金礦,提升日誌利用效率。日誌系統能解決排查問題低效的問題, 可是要解決其餘幾個痛點,還須要配套的日誌監控系統。數據庫
因此咱們最後的目標是:一套集日誌收集,查詢分析,監控報警於一體的日誌系統。tomcat
3. 選型
易用性,靈活性,擴展性的權衡安全
日誌系統做爲一個產品,它的產品功能設計和體驗相比技術更加劇要,並且技術同時也是產品,這對咱們作技術的人來講 纔是更大的挑戰,也是更大的樂趣所在。
問題1:kibana已經提供了強大靈活的日誌分析功能,咱們是否須要再作一個本身的日誌產品。
咱們的答案是須要的。靈活強大是kinaba的優勢,同時也是弱點,由於對於不少長期業務開發的同事來講,kibana,elasticsearch,lucene查 詢語法的學習成本並不算低,最主要的是平時你們使用的查詢都是相對很簡單的,分析模式也相對固定,一個web頁面的form表單,幾個簡單操 做就能完成90%以上的需求,易用性高於kibana不少,這點你們不要誤解爲對kibana的批判,並非kibana很差,只是在咱們這種場景下,咱們 更看重易用性,沒有絕對好與很差,只有是否是適合。
問題2: 已經有了開源的或收費的日誌系統,咱們是否須要作一個本身的日誌產品。
在已經有了開源的日誌方案(表明爲點評的CAT系統),也有以日誌易爲表明的收費Saas日誌服務的狀況下,咱們選擇本身開發一套 日誌系統的主要緣由是功能的可擴展性考慮。在剛開始日誌需求較爲初級的時候,現有的方案基本都能知足需求,可是做爲一個 內部日誌系統,咱們預見個性化的定製需求會層出不窮,因此輕量和功能的可擴展性咱們尤爲重視,在這樣的權衡場景裏,咱們 本身開發的日誌系統在輕量,可控性,可擴展性方面,是現成的方案是沒法比擬的。事實也證實,咱們的考慮是對的,後面不少 很重要的定製化的需求裏,若是是基於現有解決方案基本是沒法實現的。
另外關於日誌Saas服務還有一個很難克服的困難就是日誌數據自己是很重要,保密性較高的數據,通常來講,很難讓公司放心 的存入別人的數據庫。
因此在選型裏太重和靈活性一般是被捨棄的部分,咱們更偏重易用性和擴展性。這一準則也貫穿了咱們 本身在作日誌系統的時候整個過程。
4. 成果
目前日平均收集訪問日誌40+億,程序日誌10+億,程序慢日誌300W,日均UV 110,是部門整個開發團隊(包括測試)大半的人數。監控數量達到1000+,日均運行38萬次檢測。
從收到的反饋和效果來看,基本解決了前面提到的痛點。
目前監控系統已經部分開源,詳細請查看github地址: frostmourne(霜之哀傷)
5. 日誌分類
咱們將日誌分爲以下幾類:
- 程序日誌
程序日誌能夠說是最爲重要的日誌,使用log4j, nlog等日誌框架記錄程序裏一些重要事件(異常的捕獲,業務邏輯的異常等)的發生。 程序日誌都是開發人員通過思考人工埋的記錄,在全部日誌類型裏含金量最高,這些記錄在監控,排查問題中的做用舉足輕重。
- web訪問日誌
http服務調用記錄。常見的如:nginx日誌,iis日誌,tomcat訪問日誌等。從訪問日誌裏,咱們能夠獲得服務流量,整體性能,錯誤 佔比等這些很是重要的HTTP服務指標。在排查問題中一樣佔有重要的位置。
- 程序慢日誌
程序慢日誌這個概念,先解釋一下,類比數據庫的sql慢日誌,程序些慢日誌就是記下那些執行耗時較長的方法和上下文信息, 便於排查一些程序的性能問題。
- 調用追蹤日誌
APM系統大多基於調用追蹤日誌來實現,比較知名的如:zipkin, skywalking, pinpoint等,這些APM系統的實現原型基本都是來自 google發表的Dapper論文。咱們部門目前使用的是skywalking。
咱們認爲調用追蹤日誌只有在服務數量和複雜程度到至關大的體量的時候,才顯得比較重要,另外須要整個公司用一套解決方案, 造成較完整的調用鏈條才能發揮最大做用,並且有前面提到的比較成熟的單獨開源解決方案,因此在自研裏它的優先級最低。
6. 日誌系統功能介紹
技術價值最終都是須要經過產品來實現。最後咱們的日誌系統具有的主要功能(並不是全部)以下:
- 程序日誌, 慢日誌, web訪問日誌明細查詢;
用於查詢各類日誌的明細數據。能夠根據全部字段進行過濾,很是方便強大。
其中TraceId的值使用skywalking生成的TraceId,給TraceId加上連接,能夠跳轉到skywalking對應的調用鏈頁面,這樣將程序日誌和skywalking的調用 鏈日誌打通,造成互補,能夠達到很是好的體驗。
點擊上圖的TraceId連接,能夠跳轉到以下頁面:
- 慢方法分析;
能夠針對項目分析,哪些方法執行超過閾值次數最多,方法耗時各區間數量的分佈。
- http服務性能分析;
用於分析特定域名或url的性能。包括tp統計,耗時區間分佈統計。
- http服務異常流量分析;
用於分析特定域名下各url狀態碼異常的數量。
- http服務慢url分析;
用於分析某域名下哪些url耗時較長。
- 按天聚合的域名數據統計查詢,造成平常報警郵件發送給關切方。
包括每一個域名天天的pv, 500, 404, 503, 504, 平均耗時, TP90, TP95, TP99, TP99.9數據。日報郵件以下圖:
郵件將這些指標和昨天和上週指標作對比,波動幅度比較大的用紅色標記,提醒接收人注意有可能存在變壞的風險。目前 經過郵件提醒已經幫助同事提早發現若干次慢性問題。
- 站點評分
結合靜態代碼指標(單測覆蓋率,代碼複雜度,代碼質量分)和動態運行指標(流量,性能,可用性)綜合評價全部站點, 作一個排名,利於內部互相比較,瞭解本身站點各方面和別人比處於一個什麼樣的位置。
- 監控報警
做爲日誌系統,日誌的查詢和分析只能達到50%的完成度,另外的一半就是監控報警。
開源的日誌監控相關產品基本都是針對指標類時序數據的主機監控,好比:zabbix,open-falcon, Prometheus等。針對業務文檔類數據的日誌監控的項目基本沒有, 只有ElasAlert還算可用,在使用了一段時間以後,面臨不少棘手的問題:死板的調度策略(只能統一每隔x分鐘,全部監控調度一次,常常不知道堵在哪一個監控), 報警內容沒法作靈活定製,配置文件管理困難,後面咱們的配置文件數量達到200左右,一個配置文件配置不當,進程掛掉或阻塞,最後效果能夠說很不理想。 在經歷這些過程後,咱們決定自研一套監控系統。耗時1我的月上線運行。
主要功能有程序日誌監控,訪問日誌監控,慢日誌監控,http調用監控,metric監控。目前運行監控數量近800個,基本線上有問題,開發同事分鐘級別就能收到報警。 不管是從使用者的反饋和運行狀況來看,效果仍是很理想的。下面是一張咱們監控配置的頁面截圖:
下面是咱們監控產生的釘釘報警內容的截圖:
- 權限控制
目前實現了部門之間日誌隔離。
在監控建設完成後,咱們的日誌產品基礎核心功能基本完備,除了本身的功能設計以外,有不少功能是來自使用系統的同事的反饋, 感謝同事們寶貴的意見。
目前監控系統已經部分開源,詳細請查看github地址: frostmourne(霜之哀傷)
7. 系統總體結構圖
結構圖左右分開看,左半圖是日誌採集過程,右半圖是日誌存儲和使用的過程。左半圖從上往下看,右半圖從下往上看。 能夠看到Elasticsearch和kafka這對日誌的黃金搭檔。
8. 日誌格式設計
日誌系統第一個要設計的點就是要統一日誌格式,包括程序日誌,web訪問日誌。由於日誌格式若是不統一,後面採集, 存儲和數據接口開發的複雜度成倍數增長。尤爲在多語言環境的團隊,日誌格式不統一的太常見了。因此在開始作日誌系統之初, 咱們就設計了程序日誌的格式,包含了23個字段,能夠說是很是全了。web訪問日誌由於最開始收集的是iis日誌, 因此就沿用了iis日誌的標準。日誌格式統一的實現依賴現有日誌類庫良好的擴展性,咱們在log4j, nlog基礎之上很容易作到了擴展, 實現了日誌格式的統一。
這些日誌擴展已經開源,詳細請看github地址: autolog4j
9. 日誌端採集原理
目前支持兩種日誌採集方式:
- host-agent
在主機上安裝agent程序,獨立運行採集應用寫的文本日誌發送至服務器監聽端口。咱們選用的是nxlog,nxlog在資源佔用低, 穩定性,日誌發送速度這些方面都表現得很好。目前承擔了所有程序日誌,所有iis日誌和大量nginx日誌的發送任務,一直比較穩定。 有一個小限制就是一條日誌的長度,社區版本有限制,會致使過長的程序日誌沒法發送,可是這種日誌不多。
- process-agent
隨應用部署到服務器上,在應用進程內運行採集日誌直接走網絡發送至服務端。咱們直接採用大數據部門提供的log4j-appender擴展 組件集成到java應用裏。目前這種方式也很穩定,承擔了java應用訪問日誌的絕大部分採集,中間只出過一個問題,
關於兩種方式的優缺點,作一個對比矩陣:
採集方式 | 優勢 | 缺點 |
---|---|---|
host-agent | 可靠性較高, 無代碼入侵 | 每一個服務器都須要單獨安裝和配置,成本相對較高 |
process-agent | 接入基本沒成本,接入方便 | 有入侵,可靠性不如host-agent方式 |
9.1 程序日誌採集
程序日誌現成大量文本日誌,天然而然的選擇了host-agent的方式。當時主要的問題仍是日誌格式不統一的問題。 爲了保證日誌質量和下降接入成本,咱們能夠經過擴展示有的開源日誌類庫定製特定的組件,具體來說, 咱們針對log4j1, log4j2擴展了本身的layout, 針對nlog-2.0擴展了LayoutExtension;
程序日誌記錄文本而後走網絡發送還有一個額外的好處是起到冗餘備份的做用,由於日誌直接網絡發送的話,誰也沒法保證100%的可靠, 記錄了文本就能夠防止一些關鍵日誌發送失敗沒法查找的問題。雖然這種狀況不多。
目前程序日誌平均天天採集數量達10+億,磁盤佔用約700+G。
9.2 訪問日誌採集
和程序日誌相比,訪問日誌狀況要複雜得多,由於webserver種類不一,通常至少有iis,tomcat,nginx三種,並且格式 沒法統一。
iis和nginx日誌咱們採用host-agent方式,由於這兩種都已經有大量可用的文本日誌,只須要處理格式不統一的問題, 要想iis和nginx打出同樣格式的日誌是不現實的,可是咱們能夠分別爲iis日誌和nginx日誌制定統一的標準,而後在 這標準之上處理爲統一個訪問日誌,這樣成本就不會很高。
公司java應用幾乎都是tomcat應用,可是tomcat開啓訪問日誌對應用性能影響很大,因此通常咱們都會選擇關閉tomcat日誌, 這樣一來tomcat記文本這條路是不通了,這也是爲何把它和iis,nginx區分的緣由。
咱們的解決辦法是開發一個springmvc的filter攔截請求,記下日誌,而後經過process-agent走網絡發送出去。
目前訪問日誌平均天天採集數量達14億,磁盤佔用約420G
9.3 程序慢日誌採集
程序慢日誌是經過AOP的around攔截方式,記下目標方法的執行耗時,當耗時大於設定的閾值時,打一條慢日誌。發送方式採用 process-agent,考慮到程序慢日誌原本就是一種採樣的採集,對可靠性要求並無那麼嚴格,並且接入方即是咱們很是看重的一個點, 方便接入才方便推廣給你們使用。nxlog配置雖然有樣本模板,也並不複雜,可是對於沒接觸過的同事來講仍是有些犯怵致使一些理解上的障礙。
10. 服務端採集原理
10.1 日誌接收
在日誌系統無到有的過程當中,日誌的增加速度是很快的,接收端就會面臨水平擴展對客戶端 無感知的問題,這裏經過對客戶端暴露域名,使用lvs作負載均衡,後面擴展機器只須要增長域名解析 的方式實現。
logstash咱們也有在用,logstash的優勢是自帶數據處理管道, 對一些較爲簡單數據轉換清洗來講很方便,而flume若是要作清洗,就須要寫java代碼,打包上傳而後修改flume配置文件, 相對麻煩許多,可是和flume相比來講,logstash對資源的佔用要高不少,在咱們的場景只須要簡單的接收和寫入kafka, 並不須要清洗和轉換,因此這塊選擇了flume。
10.2 kafka的做用
在日誌發送速度很大的狀況下,日誌存儲數據庫Elasticsearch就會隨時面臨高寫入的挑戰,因此中間引入了高吞吐,適合 大數據場景的kafka隊列作中間緩衝。另外當elasticsearch集羣不可用時,能夠保證日誌收集不受影響,提升系統整 體的可用性也是很重要的一方面。總的來講,引入kafka能夠保證日誌接收端不會成爲一個瓶頸,進而保證對各個發送端不形成壞影響。
10.3 日誌消費和寫入
日誌的消費和寫入使用高性能實時計算框架-Storm來作,事實上spark和storm都能很好的完成這部分工做; 咱們選擇storm的緣由很簡單。公司恰好提供了Storm集羣的資源和專門的運維團隊,咱們在使用storm也有必定的積累。
在寫計算任務的時候,面臨的一個問題是,一次處理一條日誌而後寫入Elasticsearch這種簡單 處理方式吞吐量不夠,解決思路是寫操做合併,每接收100條日誌寫入一次Elasticsearch吞吐大大提升。
另一個問題是elasticsearch索引默認的refresh時間間隔是1s,在大量日誌場景,1s刷新會形成很大 的資源浪費,會有不少小段生成,對集羣壓力很大,因此這裏調整了日誌索引的刷新時間爲15s,相對會好不少。
10.4 日誌存儲優化
在收集大量日誌後,通常來講磁盤空間會成爲一個瓶頸,雖然elasticsearch默認是有數據壓縮的,可是是作了 壓縮比率和查詢性能的平衡,壓縮率並非最高,可是日誌場景,查詢性能一般並不會成爲困擾的問題,因此很適合 把數據壓縮作到最高,把索引的codec配置爲best_compression,通過對比能省出大約20%的空間。
elasticsearch集羣能管理的數據並非無限的,主要受兩方面的制約,磁盤空間和elasticsearch集羣管理的分片數量是有上限的, 超過這個限制,集羣就會出現很不穩定的問題。好在日誌數據做爲一種時序數據,它的主要價值都在最近時間段的數據裏, 歷史數據價值就小不少,因此很是適合rotate close clear。一般保留最近一個月甚至能夠更少的數據就足夠了。
另外就是日誌存儲字段類型的考慮,主要是字段是否須要分詞,是否須要全文檢索。每一個字段都要考量真實應用狀況來決定。 不須要分詞的用keyword類型;關閉norm,日誌場景一般不須要文檔得分計算,更可能是按時間排序便可。
日誌到達必定量還須要考慮分索引存儲的問題,單個索引存儲的文檔也不是無限的,分索引有兩種方法:
- 由按天存儲劃分爲更小的按小時存儲。
- 按部門劃分索引,不一樣部門日誌存放在不一樣索引裏。
咱們選擇第二種方法,緣由是第一種方法在提供查詢服務的時候,能查詢的時間範圍確定要小不少,由於查詢時間範圍越大,須要 查詢的分片數目越大,舉個最經常使用的訪問日誌查詢案例:查詢域名www.autohome.com.cn昨天的訪問日誌,方法一要查詢 24 * shard_count數量的分片, 而域名所屬的部門是肯定的,咱們就只須要查詢對應部門的索引只須要查: 1 * shard_count數量的分片,固然 查詢效率要高不少。
11. 日誌應用
系統結構圖右半部分能夠看到,咱們在elasticsearch之上作了數據接口,供日誌後臺和監控調用,還有一個獨立的監控 任務調度中心負責監控的調度。關於這部分和日誌相關技術自己干係並不大,因此不在這裏作更多的說明。
關於咱們的日誌系統主要的點就是這些,做爲一個總體的系統仍是有不少的細節沒法一一說明,若是針對某個點 想了解更多細節歡迎聯繫咱們團隊。
12. 經驗總結
- 快速原型,迭代
在需求很迫切的時候,你們須要的並非大而全的系統,極可能是一些很基礎的功能,識別這類需求快速上線是 很是重要的。因此咱們最早作的是統一程序日誌格式,收集和查詢頁面。這樣你們開始熟悉咱們的產品並快速反饋。 原型有了以後後面有許多的需求要作,這時候須要識別需求的輕重緩急,快速迭代出那些性價比高的需求,一些耗時 較長,使用率低的優先級下降。
- 重視用戶需求
用戶提出的需求雖然每每很粗糙,太細小或模糊不清,可是認真的思考用戶訴求本質是什麼,結合產品每每會產生 很酷的點子。
舉個例子,在有了不少的日誌數據以後,有小夥伴提出利用咱們的日誌數據提供一個業務系統質量評估,咱們以爲 這個想法很好,進行了進一步分析,獲得各個業務的綜合排名,讓你們看到自身系統和兄弟系統之間存在哪些差距, 對差距作出改進,進而造成良性循環。
日誌系統不少功能都來自開發小夥伴的反饋。
- 作夠用的設計
不管是產品設計和仍是技術設計,它的範圍不少時候很是寬泛,設計不足不利於進化,設計過分帶來的複雜度一樣 不利於迭代,甚至過猶不及。咱們的經驗是小團隊內部充分討論,肯定進化的方向,在保證能夠進化的前提下, 能最快上線的設計咱們認爲就是剛恰好的設計。這樣的設計每每也比較簡潔易用。