如何自己動手寫一個監(jiān)控系統(tǒng)?
1)報警配置信息的錄入
這部分比較簡單,就是一個簡單的管理系統(tǒng)
架構如下所示:
配置信息具體要存什么,看你自己需要,每個人有自己的想法
我之前的思路是:
(0)定義本配置所屬的服務,比如web服務,rpc服務,cache緩存服務,mq服務,sql服務。
(1)定義一個采樣次數(shù)的總數(shù),比如10次采樣樣本為一次計算單位。
(2)定義一個采樣樣本不過關的次數(shù),比如4次,也就是10次里面有4次樣本不過關就報警。
(2.1)單個樣本里的成功率必須>=某個閥值
(2.2)單個樣本里的平均耗時必須<=某個閥值
(2.3)單個樣本里的***耗時必須<=某個閥值(可選)
(2.4)單個樣本里的最小耗時必須<=某個閥值(可選)
(2.5)單個樣本里的TP99數(shù)值必須<=某個閥值(可選)
(2.6)其它,你想怎么做就怎么做,規(guī)則你自己定,你就是規(guī)則之王。
(3)報警周期,就是后面如果報警,多少時間之內同種類型的不再報警,如果你不需要就設置為0,那么有多少報警都會發(fā)出去,造成報警短信洪災。
單個樣本到底是啥意思? 客戶端調用埋點jar包里的API,會調用很多次,然后如果你定義了6秒鐘收割一次進行數(shù)據(jù)采樣匯總,上傳到服務器,那就是一個采樣樣本。
PS:如果在這6秒鐘某個API被調用1萬次,成功6000次,那么只會上報一條數(shù)據(jù)給遠程服務器,
類似于{key,10000,6000,...其它信息},要弄清楚這個概念,絕對不會上報1萬條數(shù)據(jù)給遠程服務器。
好,到此,針對每種服務的報警標準都已經存在mysql數(shù)據(jù)庫了。
有的時候,用戶(單位內部各個業(yè)務系統(tǒng))會說,我需要每種服務的參數(shù)都要定制,那么你需要自己擴充這些達到定制的需求,
還有說我針對時間段的需求要定制,我針對每個URL的參數(shù)要定制,這個你自己舉一反三就可以了。
2)業(yè)務統(tǒng)計信息上報
這部分代碼在client_metrics里已經實現(xiàn)了,花時間看一下就知道設計思路。
上報的時候要包含以下一些信息
{產品,所屬服務,機器ID,key,total調用次數(shù),成功次數(shù),平均耗時,***耗時,最小耗時,TP99...等其它你想要的信息}
這里解釋一下前4個字段的意思。
舉個例子:
產品:公司金融產品
服務:因為這個產品會包含一些http服務啊,rpc服務啊,緩存服務啊,sql服務啊,所以你要標記出來。
機器ID:就算你指定了rpc服務,你不會只部署一臺吧,你肯定有多臺,那你得指定是哪一臺啊,不然不知道發(fā)生在哪臺機器上啊,這個你可以寫一個
靜態(tài)函數(shù)獲取,比如我們采用了發(fā)送時獲取{ip:本進程監(jiān)聽端口}這樣,以后就不再重新獲取,復用這個值。
key:針對http服務,就是你的url; 針對redis服務,就是你的命令;以http服務為例,你的url如果有變化的參數(shù),你要寫成模板類型的值,不然key的個數(shù)
發(fā)生爆炸,比如http://ip:port/a/1/b 這樣的,里面的1會發(fā)生變化,你不能直接把這個作為key,你得寫成http://ip:port/a/xxx/b,大概就這個意思。
有的人說埋點你不能影響我的業(yè)務速度,不能影響我的內存,這個在設計時候都要考慮
還有如果監(jiān)控的數(shù)據(jù)接收服務器全部宕機了,也不能影響業(yè)務,這個請自己看client_metrics,看完了就知道大體思路了,如果你覺得可以優(yōu)化得更好你自己優(yōu)化吧。核心思想是異步上傳,容許一段時間的數(shù)據(jù)不是100%準確(發(fā)生在所有遠程數(shù)據(jù)接收服務器全部宕機的前提下)
另外我們當時做數(shù)據(jù)匯總時,以web為例,web可能會有幾十個URL的數(shù)據(jù),我們上傳時就已經做了所有數(shù)據(jù)的一個綜合統(tǒng)計,比如所有url的調用次數(shù),平均耗時,這樣后面如果你要看這些數(shù)據(jù),直接用這些數(shù)據(jù)作為計算基礎就可以了。
然后我們還做了一個掉0檢測,就是如果某個新的key***次出現(xiàn)時,我們在內存中記住了它,如果它在某個采樣周期內沒有出現(xiàn),我們就會上報這個key的數(shù)據(jù)為0,有些場合可以用來做掉零檢測。
另外如果你不是java語言的程序,怎么埋點?一個可行的是你用Netty寫一個UDP服務器,內部嵌套上面的java jar包,本質上是做了一個代理
然后所有程序發(fā)送UDP數(shù)據(jù)給你,這里可以優(yōu)化,思路你自己想,(maybe QUIC協(xié)議你可以調研一下)
好,數(shù)據(jù)到了Netty服務器之后,這里是HTTP協(xié)議上報的哈,為什么要一份為2,一式2份呢?
目的是為了數(shù)據(jù)上傳入HBase和數(shù)據(jù)入MQ互相不干擾,也就是說,hbase全部宕機不影響數(shù)據(jù)進MQ,MQ全部宕機不影響數(shù)據(jù)入hbase.
hbase:用來存儲海量歷史數(shù)據(jù),這樣如果你收到了報警信息,你可以查啊,調出那個時候的數(shù)據(jù)看是不是真的有問題,用于歷史回溯。
mq: 用于存數(shù)據(jù),作為實時計算的數(shù)據(jù)源啊,不然誰來發(fā)送報警短信和郵件呢?
然后hbase那里有一個redis.這個是干嘛的?因為每個數(shù)據(jù)里面的產品我可以實現(xiàn)定義在配置庫里,但是服務,機器ID,key這些是完全動態(tài)的啊
所以每一條數(shù)據(jù)來了后,要需要先查redis是否存在,不存在的話,要相應的維護到hbase里的表里,這樣慢慢構建好這個產品的這些信息,回頭在界面上才可以調出來。所以redis就是起加速作用,不然每一條信息來了,你也不知道服務和機器id,key是不是已經存在了的,然后插入到hbase,很慢啊,量大了你肯定扛不住。
具體的技術很多,storm,flink,heron都可以的,你熟悉哪個用哪個。
保證同一個[產品,服務,機器ID]的數(shù)據(jù)肯定是到同一個bolt就行,這樣才好做計算,否則如果分散了,那就不好計算了。
計算的標準怎么拿?從步驟1的報警配置信息庫里拿啊,所以每個bolt啟動時從sql庫里拿,
建議在1)的架構里開一個HTTP API接口,這樣bolt每次啟動前初始化先拿取相關的配置信息,然后后面定時拉取更新本地配置
這樣你如果修改了配置信息,自然會更新到bolt里,不用重啟storm程序。
實際上有很多需要注意的細節(jié)
比如如果HTTP接口調用失敗怎么辦,那就繼續(xù)保持原有的配置信息不需要替換。
如果新的配置跟老的配置有沖突怎么辦,比如老的是10條數(shù)據(jù)有6次失敗就報警,目前已經有了8條數(shù)據(jù),還差2條,然后刷新了新的報警配置是6條數(shù)據(jù)3次失敗就報警
,你怎么解決就看你自己了,合理就行。
我們當時做報警郵件的時候,郵件內容一部分是用戶定的報警標準,下面是每一條信息的具體數(shù)值,然后告訴你這條數(shù)據(jù)是否達標。
(死也得讓你知道為啥死的 :)
這里報警的時候,就用到了你的參數(shù)里的報警周期,這個參數(shù)怎么用?比如你定義[產品,服務,機器ID]這個組合1分鐘只能報警1次,假設服務是web的話,就算有很多個URL都報警了,我也只會在這1分鐘內報警1次,具體怎么玩你自己定,否則業(yè)務一下子收到幾十個報警短信,他會覺得很無助,其實也沒必要發(fā)這么多條,你懂我的意思就好。游戲規(guī)則自己定吧。
注意每一個細節(jié),力求***。
4)最終的架構圖
最終完整的架構圖如上所示。
5)細節(jié)和性能分析
有人會問,如果業(yè)務越來越多,我怎么知道我的監(jiān)控系統(tǒng)是否要擴容?
很簡單,你把2)步驟里面的netty服務器里面的2個內存隊列的size做監(jiān)控信息采集,同樣上報給后端,同時在1)里面設置好報警參數(shù)
也就是你做了一個自監(jiān)控,一旦內存隊列的size超過了閥值,說明輸入的速度>輸出的速度啊,嗯,跟老板申請擴容吧
可以是加web服務器,也可以是提高后面的處理速度,自己分析吧。
招一個好一點的大數(shù)據(jù)人員,維護好hbase,storm這些,這套系統(tǒng)就可以水平擴展了,
不管你一天有多少T的數(shù)據(jù)量,照單全收,毫無壓力。
另外附上我們之前生產環(huán)境的數(shù)值:每天300G數(shù)據(jù),沒辦法,不是大公司,沒這么多的產品,而且很多中臺產品都是1分鐘上報1次,頻率有點低,其實幾秒鐘上報1次都是可以的,這樣很快可以發(fā)現(xiàn)哪個業(yè)務出了問題,也可以做到秒級感知啊 :) 。
PS:因為時間有限,最近在研究別的東西,這個項目的代碼不會經常更新,附上架構圖給各位網友,
以此為藍本,加上你的自由發(fā)揮的能力,沒問題。
另外有興趣做HDFS數(shù)據(jù)入庫的可以看看我的另外一個項目MyHDFS,從前同事得知***的數(shù)據(jù)是 5000萬條數(shù)據(jù)/單日(其實寫幾個億絲毫沒有問題)
附錄:
http://git.oschina.net/qiangzigege/MyEye 里面談到了每種技術具體可以用的技術選型,就看你熟悉哪個了
http://git.oschina.net/qiangzigege/MyHDFS
大牛很多,只敢拋磚引玉,肯定有設計不當和不周的地方,還請各位大牛輕噴,謝謝!
MyEye官方討論群 120734278 想做監(jiān)控的可以內部自由討論。
另外最近看到阿里的監(jiān)控,除了常規(guī)數(shù)據(jù)統(tǒng)計和報警外,給我印象最深的是智能監(jiān)控,我只能說阿里人才就是多啊 :)
這套系統(tǒng)是15年9月份開始寫的***行代碼,15年10月中旬第1版上線使用,只花了1個半月。
我做總體架構設計和API設計,物理庫設計,code review,只有1個小弟負責代碼編寫.
當時2個人沒有任何雜念的全身心投入到這個產品中,經常回家都在思考白天的代碼有沒有問題。這段時間也是很懷念的。其實在做這個監(jiān)控系統(tǒng)之前我從來沒有做過監(jiān)控,當時領導讓我設計監(jiān)控的時候我真是一臉懵逼,到處問人有沒有經驗可以借鑒,問了一圈發(fā)生公司沒有任何一個人可以幫到我,于是定下心來自己完全琢磨每個細節(jié)該怎么設計,開發(fā)過程中小弟也提出來一些很好的建議,后來發(fā)現(xiàn)一些想法在別的開源軟件中也是存在的,所以說這個系統(tǒng)沒有參考任何一款軟件,***開發(fā)出來并且非常平穩(wěn)的運行了1年半時間我還是挺高興的。
實際上,公司內部任何需要監(jiān)控的信息點,只要稍微轉換下,都可以用同一個API來上報信息
所以我們當時也做了平臺部門MQ消息中間件的負載監(jiān)控,大數(shù)據(jù)部門的信息采集指標健康監(jiān)控。
https://my.oschina.net/qiangzigege/blog/600441
是當時給公司上面匯報用的PPT。
后記: 當時做完這套監(jiān)控系統(tǒng)的時候,壓根還不知道有調用鏈這個東西的存在,也沒有領導和同事提出這個需求,否則當時肯定也直接給加上去了,后來把zipkin的源碼翻完之后才發(fā)現(xiàn)調用鏈比做監(jiān)控更簡單,以后有時間再講講調用鏈的本質以及以 zipkin為例子如何上報調用信息。