關(guān)于監(jiān)控,在各個技術(shù)網(wǎng)站,幾乎都是一搜一大把。幾個大的互聯(lián)網(wǎng)公司,也都有開發(fā)自己的監(jiān)控系統(tǒng)。 關(guān)于這方面也有不少分享。 這里介紹針對支付系統(tǒng)的監(jiān)控和報警,但大部分內(nèi)容,應(yīng)該來說,對其他系統(tǒng)也是通用的 。
現(xiàn)在基本上 Zabbix 成為監(jiān)控的標(biāo)配了。 一個常規(guī)的 Zabbix 監(jiān)控實現(xiàn), 是在被監(jiān)控的機器上部署Zabbix Agent,從日志中收集所需要的數(shù)據(jù),分析出監(jiān)控指標(biāo),發(fā)送到zabbix服務(wù)器上。!zabbix 監(jiān)控這種方式要求每個機器上部署 Zabbix 客戶端,并配置數(shù)據(jù)收集腳本。Zabbix的部署可以作為必裝軟件隨操作系統(tǒng)一起安裝。
先說相對比較簡單的系統(tǒng)監(jiān)控,一般系統(tǒng)監(jiān)控關(guān)注如下指標(biāo):
CPU負(fù)載
內(nèi)存使用率;
磁盤使用率;
網(wǎng)絡(luò)帶寬占用
這些指標(biāo)在zabbix agent中會提供默認(rèn)實現(xiàn),通過簡單配置即可激活。裝機時可以考慮統(tǒng)一配置這些監(jiān)控。
JMX提供了關(guān)于JVM的大部分核心信息,啟動時設(shè)置參數(shù),支持遠(yuǎn)程訪問JMX,之后即可通過接入JMX來實時讀取JVM的CPU,內(nèi)存等信息。zabbix也支持通過JMX來獲取信息。
服務(wù)監(jiān)控主要指接口的狀態(tài)監(jiān)控。 服務(wù)監(jiān)控關(guān)注如下指標(biāo):
QPS,每秒請求數(shù) 對于使用容器的系統(tǒng),包括Apache Tomcat,Resin,JBoss等,可以從Access Log中采集到每個接口的QPS。沒輸出Access Log的系統(tǒng),考慮通過Annotation來規(guī)范輸出訪問計數(shù)。當(dāng)然,這個指標(biāo)還可以細(xì)分為 每秒成功請求數(shù)、失敗請求數(shù)、總請求數(shù)等。
請求響應(yīng)時間 在服務(wù)器端監(jiān)控每個接口的響應(yīng)時間。簡單做法是在方法執(zhí)行前后打時間戳計算,對于HTTP請求,也可以從access log中獲取接口執(zhí)行時間。當(dāng)然也可以用annotation來實現(xiàn)統(tǒng)一的執(zhí)行時間監(jiān)控。
執(zhí)行異常數(shù) 指程序運行過程中發(fā)生的未捕獲處理的異常,一般是對場景考慮不周導(dǎo)致的異常發(fā)生,比如空指針、錯誤參數(shù)、數(shù)據(jù)訪問等的異常。 這些異常一旦發(fā)現(xiàn),需要修復(fù)代碼邏輯。 異常在應(yīng)用日志中一般都會把錯誤堆棧打印出來。
監(jiān)控項目 | 監(jiān)控數(shù)據(jù) | 數(shù)據(jù)源 |
---|---|---|
系統(tǒng)監(jiān)控 | CPU使用率 | zabbix agent默認(rèn)采集 |
系統(tǒng)監(jiān)控 | 內(nèi)存使用率 | zabbix agent默認(rèn)采集 |
系統(tǒng)監(jiān)控 | 帶寬使用率 | zabbix agent默認(rèn)采集 |
JVM內(nèi)存監(jiān)控 | free, used, heepsize | JMX |
GC監(jiān)控 | GC內(nèi)存 | GC 日志 |
GC監(jiān)控 | GC內(nèi)存回收時間 | GC 日志 |
Tomcat監(jiān)控 | 最大會話數(shù)、會話數(shù)、互動會話數(shù) | JMX |
Tomcat監(jiān)控 | 最大線程數(shù)、當(dāng)前線程數(shù)、繁忙線程數(shù) | JMX |
服務(wù)狀態(tài)監(jiān)控 | 404/505等status數(shù)量 | Tomcat訪問日志 |
服務(wù)狀態(tài)監(jiān)控 | 每個接口的訪問量 | Tomcat訪問日志 |
服務(wù)狀態(tài)監(jiān)控 | 每個接口發(fā)送的字節(jié)量 | Tomcat訪問日志 |
服務(wù)狀態(tài)監(jiān)控 | 每個接口的最大響應(yīng)時間 | Tomcat訪問日志 |
服務(wù)狀態(tài)監(jiān)控 | 每個接口的最平均響應(yīng)時間 | Tomcat訪問日志 |
服務(wù)監(jiān)控 | 錯誤數(shù) | 應(yīng)用日志 |
數(shù)據(jù)庫是大部分應(yīng)用的核心和瓶頸,對其監(jiān)控尤其必要。監(jiān)控可以 在應(yīng)用側(cè)執(zhí)行,也可以在數(shù)據(jù)庫服務(wù)器上做。前者通過應(yīng)用代碼中打印日志來實現(xiàn),或者直接override 鏈接池中相關(guān)方法來統(tǒng)一輸出日志。在數(shù)據(jù)庫服務(wù)器上執(zhí)行監(jiān)控,需要根據(jù)數(shù)據(jù)庫的特點分別設(shè)計方案。以MySQL為例,可以通過監(jiān)控其bin log來獲取執(zhí)行的sql語句以及執(zhí)行時間。使用Alibaba Canal 來對接MySQL 的BinLog, 接收到BinLog消息后,解析消息數(shù)據(jù),可以獲取請求的SQL、參數(shù)、執(zhí)行時間、錯誤代碼等信息。
數(shù)據(jù)庫監(jiān)控重點關(guān)注如下指標(biāo):
每秒請求數(shù)
慢查詢處理數(shù)
SQL語句執(zhí)行時間
調(diào)用鏈監(jiān)控指在微服務(wù)系統(tǒng)中,跟蹤一個請求從發(fā)起到返回,在各個相關(guān)系統(tǒng)中的調(diào)用情況。 調(diào)用鏈監(jiān)控是跨系統(tǒng)的監(jiān)控,需要在請求發(fā)起時分配一個可以唯一識別本次調(diào)用請求(或者成為事務(wù))的ID,這個ID會被分發(fā)到每個調(diào)用上。之后在調(diào)用日志中輸出該ID。當(dāng)所有日志都匯總起來后,可以從日志中分析本次調(diào)用的流程。對于HTTP/HTTPS請求,可以考慮將ID放到Header里面,這樣不會影響接口邏輯。
業(yè)務(wù)監(jiān)控是一個復(fù)雜的話題。這里以支付為例,說明業(yè)務(wù)監(jiān)控的架構(gòu)和實現(xiàn)。
每個支付通道監(jiān)控包括如下內(nèi)容:
支付通道接口請求數(shù): 如果一段時間內(nèi)接口請求環(huán)比大幅度下降,可能是該接口出現(xiàn)問題了。
支付通道接口請求失敗數(shù),即調(diào)用接口失敗的數(shù)量。
支付通道接口請求延遲。
支付通道支付失敗率。每個通道支付有一定的失敗率,如果給定時間內(nèi)突然有超過這個失敗率的情況出現(xiàn),則可能是通道出現(xiàn)問題了。
支付通道同步、異步調(diào)用次數(shù)。
支付接口,如支付、提現(xiàn)、退款、簽約、訂閱等,監(jiān)控如下內(nèi)容:
總金額,如果總金額有大的波動,則有洗錢的可能。
每筆平均金額。
支付成功率
實際上對一個業(yè)務(wù)來說,大部分系統(tǒng)監(jiān)控的指標(biāo)是類似的,而按照這種方式,每個指標(biāo)在各個被監(jiān)控系統(tǒng)中還需要單獨寫腳本實現(xiàn),工作量大。針對這種情況,可以采用日志集中監(jiān)控的方式來處理??紤]到日志最終都需要歸并到一個日志倉庫中,這個倉庫可以有很多用途,特別是日常維護(hù)中的日志查詢工作。多數(shù)指標(biāo)可以在日志上完成計算的。 借助這個系統(tǒng),也可以完成監(jiān)控:!zabbix 監(jiān)控
日志通過Apache Flume來收集,通過Apache Kafka來匯總,一般最后日志都?xì)w檔到Elastic中。 統(tǒng)計分析工作也可以基于Elastic來做,但這個不推薦。 使用Apache Spark 的 Streaming組件來接入Apache Kafka 完成監(jiān)控指標(biāo)的提取和計算,將結(jié)果推送到Zabbix服務(wù)器上,就可以實現(xiàn)可擴展的監(jiān)控。 這個架構(gòu)的優(yōu)勢在于:
監(jiān)控腳本的跨系統(tǒng)使用。 指定日志規(guī)范后, 只要按照這個規(guī)范編制的日志,都可以納入監(jiān)控,無需額外配置。
服務(wù)重新部署時無須考慮監(jiān)控腳本的部署,所有監(jiān)控直接生效。
難點在于,提煉一套通用的日志規(guī)范,考慮如何通過Spark來分析日志。
Flume和logstash都可以用于日志收集,從實際使用來看,兩者在性能上并無太大差異。flume是java系統(tǒng),logstash是ruby系統(tǒng)。使用中都會涉及到對系統(tǒng)的擴展,這就看那個語言你能hold住了。
flume和logstash都支持日志直接入庫,即寫入hdfs,elastic等,有必要中間加一層kafka嗎?太有必要了,日志直接入庫,以后分析就限制于這個庫里面了。接入kafka后,對于需要日志數(shù)據(jù)的應(yīng)用,可以在kafka上做準(zhǔn)實時數(shù)據(jù)流分析,并將結(jié)果保存到需要的數(shù)據(jù)庫中。
Streaming分析,可以走spark,也可以用storm,甚至直接接入kafka做單機處理。這取決于日志數(shù)據(jù)規(guī)模了。spark streaming是推薦的,社區(qū)活躍度高,又集成了多種算法。
Java主流的日志系統(tǒng)有l(wèi)og4j,JULlogback等,日志框架有apache commons logging,slf等,關(guān)于這些系統(tǒng)的歷史掌故恩怨情仇八卦趣事,網(wǎng)上有不少資料,這里不詳細(xì)介紹。
最好的編程語言是PHP還是Java? 同樣的,也有爭論:最好的日志框架是slf還是commons-logging?最好的日志系統(tǒng)是Log4j還是Logback?在使用上,它們的API和使用方式大體類似,slf有模版支持,但這也不是關(guān)鍵需求。而性能方面,從我們測試用例中也沒有發(fā)現(xiàn)哪個系統(tǒng)或框架有明顯優(yōu)勢。對性能有決定性影響的是使用方式。
根據(jù)我們的測試,在高并發(fā)系統(tǒng)中,關(guān)于日志,有如下結(jié)論:
Log4j與logback在高并發(fā)下性能上并無太多差異,不用太糾結(jié)使用哪個API,.影響性能的是日志內(nèi)容的寫法和數(shù)據(jù)量
輸出類名和行號會嚴(yán)重影響性能,這需要使用到性能不佳的反射機制。執(zhí)行頻率高,性能要求高的代碼,禁用反射,禁用new操作。
高峰期系統(tǒng)出錯,如果打印錯誤堆棧,那絕對是雪上加霜,理由同上。
多線程時輸出日志,寫鎖是影響性能的關(guān)鍵因素。緩解寫鎖的措施,首選加大日志寫入緩沖區(qū),其次是異步打印。異步對性能有提升,但不顯著。寫鎖出問題的一個現(xiàn)象是CPU跑滿。
日志分級本身無太大意義。
他山之石,可以攻玉
感謝您對本文的關(guān)注,如需要及時收到鳳凰牌老熊的最新作品,或者有相關(guān)問題探討,請掃碼關(guān)注“鳳凰牌老熊”的微信公眾號,在公眾號里留言或者回復(fù),可以盡快處理,謝謝。
聯(lián)系客服