概述
線上系統掛了,服務異常了,響應超時了;系統運行結果不符合預期。。。
用戶被影響,甲方爸爸不開心,後果很嚴重。<br> 從某種意義上講,“在用戶遇到問題之前把問題解決,問題也就不算問題了”。
文章概要:線上環境痛點》解決方案》想象空間。
1、痛點
以下痛點是本公司實踐中遇到的痛點,痛點或許不具備通用性,但思路卻可以借鑑。
1.1、在服務發佈時,我們經常會遇到如下的問題
服務剛發佈,是否部署成功;
服務剛發佈,版本是否正確(實例運行版本是否是我想要部署的版本);
服務剛發佈,文件是否缺失;
如果服務實例較少,挨個上服務器檢測,也是可行的,但目前稍微有點用戶的系統,都是多實例部署,一個機房動輒幾十上百個實例,挨個上服務器費時費力。
事實上,如果CI & CD 給力,以上問題都將不再是問題。
1.2、在服務發佈後,也會有如下問題
服務是否可用;
單個服務可用,但系統鏈路是否暢通呢;
同一個機房不同實例代碼是否一致(人工疏忽、運維繫統 等問題導致不一致);
此外,我們公司還涉及本地化部署(將公司系統打包部署到其他公司),本地化部署一段時間需要部署新版本,但我們卻不知道上次部署的系統是什麼時候的版本。直接部署最新版本?系統太大,關聯繫統太多,所有系統部署最新版本,部署及驗證耗時費力,成本太高,肯定不行。
1.3、管理訴求
發佈故障:在發佈完成後有故障則立即告警;
系統運行故障:運行有故障則立即告警,力爭比用戶早發現異常;
監控自動化:總不能挨個實例看控制檯吧;
接收告警方便高效:相關責任方能方便接收到消息(不考慮郵件);
監控系統本身穩定:沒有收到告警就一定是沒有故障嗎,是否是監控系統本身故障了呢;
2、解決方案
目前市面上有很多的監控系統,穩定高效、歷經衆多大廠生產系統檢驗,如Zabbix、Prometheus(普羅米修斯)等。
但最終我並沒有選擇這些監控系統,而是自己搭建一套。爲什麼自己構建,自己搭建的比他們更優秀嗎,當然不是。
更優秀的不一定是最好的,更合適的纔是最好的。
自行搭建監控系統原因如下:①這些系統太重,而我僅僅是監控一個業務模塊的幾個服務而已;②這些系統屬於公司級別的監控,需要公司級別去推行,而我需要的是幾天就能上線監控系統;③這些系統面向大衆,監控方案也是通用的,而我需要自己定製化一些監控指標。
通用的東西不易做精細,越定製化,做好的概率越大。
2.1、監控如何做
2.1.1、服務正常運行監控
監控端口是否可行呢?肯定不可行,端口通信正常,並不代表服務正常,所以最終選擇在服務裏新增專用的監控接口;
2.1.2、監控告警通知
郵件?直接pass,誰會整天看郵件呢,公司用釘釘,所以最終選擇了釘釘羣機器人;
2.1.3、告警內容
越少越好,只告警真正核心的內容,否則通知氾濫,反而沒人關注了,公司那麼多系統監控的郵件你看了多少呢?如果確實有大量內容需要通知(不是告警),請使用單獨的羣通知。
2.2、監控實現-代碼改造
不推薦使用業務接口用於監控,監控接口應該支持快速響應且資源消耗極低。
當然,做業務級別的監控除外,業務級別監控應合理評估資源消耗,不能影響正常業務。
2.2.1、服務運行監控接口
代碼中新增獨立的監控接口,請求接口返回數據則表示服務正常;
@ApiOperation(value = "測試接口")@RequestMapping(value = "/test", method = RequestMethod.GET)public int test() { return 1; }
以上接口簡單粗暴,返回1則表示正常,這也是第一個版本的監控實現。
最新版本的監控接口如下,原因見【相同機房不同實例版本一致監控】。
@ApiOperation(value = "查詢當前服務版本號,開發版本號_修改版本號")@RequestMapping(value = "/getVersion", method = RequestMethod.GET)@ResponseBodypublic String getVersion() { String version = new StringBuilder().append(Version.developVersion).append("_").append(Version.modifyVersion).toString(); return version; }
2.2.2、系統鏈路監控
對於固定業務而言,整體的系統鏈路是固定的,系統A調用系統B,系統B調用系統C。所以直接在A、B 、C系統中新增調用鏈接口,監控時僅需監控最上層服務A,如果調用鏈路有異常,則告警。
@ApiOperation(value = "測試服務調用鏈,返回調用鏈上的 log.AppName,服務IP,當前時間戳")@RequestMapping(value = "/testCallChain", method = RequestMethod.POST)@ResponseBodypublic String testCallChain(@RequestBody CloudRequestVo<String> cloudRequestVo) throws Exception { String localVersion = new StringBuilder().append(cloudRequestVo.getCloudTraceID()).append(" ==> ").append(LogUtil.getCloudTraceID()).toString(); String nextService = bServiceFeignClient.testCallChain(cloudRequestVo); return new StringBuilder(nextService).append(" <== [").append(LogUtil.getCloudTraceID()).append("]").append("[ServiceStartTime]").append(serviceStartTime).append("[Version]").append(getVersion()).toString(); }
仔細看代碼,會發現服務響應內容中包含了調用鏈上每個服務的響應信息,這些信息裏包含了CloudTraceID(含有當前實例IP、當前實例名字、當前請求時間)、ServiceStartTime(系統啓動時間)、Version(系統版本信息);
2.2.3、相同機房不同實例版本一致性監控
細心的同學可能會發現,在【系統鏈路監控】中服務的響應數據包含了系統版本信息(Version),這個便是用於監控相同機房不同實例版本是否一致。
監控原理:
①開發人員完成開發後,只要需要發佈生產就必須修改代碼中的版本信息,版本號加1;
②監控腳本請求同一個機房相同服務後,若發現返回的版本信息不一致,則告警;
或許有同學會說,這種手段需要人爲修改代碼,忘記修改怎麼辦?
我們公司用的是Jenkins編譯,所以我修改了相關代碼,Jenkins編譯時會校驗版本號是否遞增,如果未遞增,則直接不允許編譯。
/** * Desc: 版本信息. * developVersion:開發版本號,必須與SVN地址上的版本號一致(格式請勿改變,只能修改數字,否則Jenkins可能不允許編譯)。 * modifyVersion:修改版本號,每次修改代碼只要需要編譯發佈就必須遞增該版本號,加1即可(格式請勿改變,只能修改數字,否則Jenkins可能不允許編譯)。 */public class Version { // start public static int developVersion = 8102; public static int modifyVersion = 9; // end // 注意:start、end中間不能加任何東西,只允許修改版本號。}
Note:
爲避免監控接口地址和業務接口地址衝突,建議所有監控地址統一前綴,如:
服務運行監控接口地址:IP:PORT/test/getVersion ;
系統鏈路監控地址:IP:PORT/test/testCallChain;
相同機房不同實例版本一致性監控接口地址:直接使用getVersion接口返回數據,不單獨開接口;
PS:版本一致性監控,最初考慮使用命令SSH連接遠程服務器執行shell腳本做校驗,此方案太繁瑣被pass了。
2.3、監控實現-監控及告警
2.3.1、開啓釘釘羣機器人
釘釘羣機器人用於接收告警信息。如何開啓釘釘羣機器人,此處不贅述了。開啓機器人後,拿到webhook地址,則可以使用http請求向釘釘羣發消息了。
詳細說明參考釘釘開放平臺文檔:https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq 。
2.3.2、監控實現
準備工作:
待監控實例的IP、端口,並按實例及機房分組;
待監控業務的頂層實例IP、端口;
監控邏輯:
定時請求監控接口,如果有異常,則調用釘釘機器人接口告警。
監控頻率:
頻率不宜過高,影響業務就不好了。(PS監控接口都是相當輕量的接口)
調用鏈監控頻率建議設置長一些,畢竟服務連通性正常,調用鏈異常可能性較少。
監控正常通知:
沒有收到告警就一定是沒有故障嗎,是否是監控系統本身故障了呢。鄭州不孕不育那家好:http://www.zzfkyy120.com/
所以還需要每天定時向監控羣發個通知“XXX監控運行正常”。
2.3.3、監控平臺
只要能訪問生產服務,且能發起Http請求就可以。
我使用的是 XXL-JOB作爲監控平臺,直接使用GLUE模式,可以隨時完善監控代碼,並查看監控系統運行日誌。使用教程可以查看XXL-JOB官方教程http://www.xuxueli.com/xxl-job/#/。
公司同事可直接聯繫我獲取監控腳本,替換待監控實例的IP端口即可使用(在新增專用測試接口前可臨時使用已有接口)。
3、想象空間
3.1、告警渠道多元化
釘釘、微信、電話、企業內部通訊工具,只要渠道支持http請求就行。
3.2、業務監控
①業務級別監控、實例內部定製數據監控;
②集成已有監控系統,很多企業使用ELK作爲日誌系統,並有很多監控面板,完全可以採集監控面板的數據做通知告警。
3.3、自動化測試
當業務穩定後,完全可以實現自動化測試。代碼一發,自動化測試一跑,發現並解決基礎異常後,QA才介入進行復雜場景的測試,甚至當複雜業務場景的數據接收及響應數據的結構穩定清晰後,複雜場景也可以自動化測試。鄭州不孕不育醫院有哪些:http://wapyyk.39.net/zz3/zonghe/1d427.html
3.4、其他通知場景
非得是系統監控告警嗎?有了釘釘羣機器人,任何提醒都可以做,比如重要的線上業務的階段性通知,甚至是一些定時提醒。
4、後記
此監控系統從1月份上線,已經迭代優化運行半年多了。現在每天最開心的事情就是早晚收到監控系統正常運行的通知,而其他時間都不收到異常通知。此監控系統也確實在服務部署及線上運營過程中爲我們提前發現了很多問題。http://dalian.huodong.dqccc.com/exposition/detail-2237281.html
監控做了,系統就無憂了?告警了但沒人從根本上解決問題,也並沒什麼卵用;兄弟業務團隊的系統異常也可能互相影響。真正的系統高可用,得公司發力,從系統架構、業務、管理等方面綜合下手,就不BB了。 當然自己的業務模塊自己必須負責。
如果是一個業務模塊,這套監控系統的思路或許很適合,如果是大規模微服務做統一監控,建議還是使用市面上成熟的監控系統。
思路比工具更重要,想象空間留給大家。
最後上張監控告警圖片吧: