商業版的性能監控平臺確實強大,但是對於很多初創公司來說,一般不會選擇昂貴的商業監控平臺,更多的是選用開源的監控系統,比如Zabbix。但是無論多麼強大的開源監控平臺,基本都不能滿足所有的監控需求,比如沒有APM監控,不方便監控mysql、Postgresql等數據庫,所以集成化開發是一種可行的選項,只要做好前期技術選型,選好要被集成的監控工具,我們就可以邁出第一步。
由於一直對Telegraf + Influxdb + Grafana有比較多的實踐經驗,並且這種監控組合已經被很多人大量的採用,原因是輕量化、部署快捷、自由配置監控面板、豐富的圖形化展現,最最重要一點是Telegraf能配置出多達幾十種監控模型(並且Telegraf的監控插件還在不斷擴展中),提供一下官網的Telegraf監控配置說明:https://github.com/influxdata/telegraf/tree/release-1.9/plugins/inputs,細看就能發現其對大量監控指標的支持(包括支持docker的監控)。除了Telegraf,結合Jmxtrans還可以對所有Java服務進行全面的監控(參考我的另一篇文章https://blog.csdn.net/smooth00/article/details/90399528),如果需要有APM監控,那選用Skywalking是最明智的,原因是它具有良好的擴展性,並且還在不斷演繹和發展中,只要解決好數據存儲的問題,就可以被我們所用(關於這塊可以參考我的文章https://blog.csdn.net/smooth00/article/details/96479544)。
以下是我根據這些設想編制的架構圖,整體來說已經按照這個圖在一步步的實現:
由於是集成的,所以平臺的整體性能將取決於Influxdb、Grafana、Skywalking本身的性能,但開源技術的好處就是可以無限擴展,Influxdb和Skywalking都支持高可用的集羣化部署,想做多大的生意就看你願意裝多大的門店了。另外監控平臺的數據傳輸性能,也會受制於推拉模式原理的限制,如下圖所示:
這兩種模式的的特點如下:
推模式(Push):是指由監控客戶端主動將監控數據推送給監控服務器。Push模式的實時性和數據一致性較好,但是效率較低。Push操作的頻率一般由設定好的時間間隔觸發,一旦時間間隔設置不當,可能會造成丟失監控數據的現象,或者是推送的數據過多,前者影響了監控系統的準確性,而後者則增加了通信開銷。
拉模式(Pull):是指由監控服務器端採用輪詢的方式通知客戶端,將被請求的監控數據項發送給服務器端。Pull模式的針對性強,能夠滿足個性化需求,並可以減少通信開銷,但是一致性和實時性一般。如果輪詢的次數頻繁,以及需要輪詢的客戶端較多,則服務器端的壓力就會變大。
毫無疑問的是我們所採用的telegraf + influxdb;jmxtrans + influxdb;skywalking 三個監控都是基於推模式(Push),好處就是實時性和數據一致性好,適合於在壓測時的監控(這也是爲什麼我採用它們來集成到監控平臺,因爲本人就是個性能測試工程師,關注的當然是監控的準確性和實效性)。但是這樣很可能就不太適用於大批量服務器部署情況下的運維監控了,因爲推模式需要在大量客戶端中配置數據發送的時間間隔,這本身會很麻煩,時間設小了通信開銷太大,數據庫的寫入壓力過大,時間設大了可能又不滿足監控的個性需求;相對來說拉模式適合於運維監控,因爲運維監控都是7*24小時監控,時間粒度不大基本上不用頻繁輪詢,通信開銷可控,數據庫的寫入壓力較小,監控平臺的穩定性自然就高。所以以上的架構設計,對於運維性監控可能不夠滿足,在實踐中還需要加入通過遠程來配置各個監控代理的Push時間間隔的功能,這就加大了操作的麻煩度。從開源集成來說,如果要採用拉模式(Pull),通過Prometheus + exporter的模式(與傳統的數據採集組件不同的是,exporter並不向中央服務器發送數據,而是等待中央服務器主動前來抓取)可以實現。不過從安裝部署來看,面對大量不同類exporter組件的部署和配置,不少人還是會心生恐懼,所以集成telegraf + influxdb的方式雖然不是最好的選擇,但就眼下來說,卻是最經濟的選擇(不過網上有人願意基於Prometheus開發自已的exporter,能駕馭就是好,開發自己的監控平臺無需排斥任何一種開源技術)。
另外以上架構還有個有問題是不好解決的,那就是如何管理監控的報警。作爲監控平臺的核心功能之一,報警和預警無疑是衡量監控平臺好壞的點。Grafana本身可以配置報警功能,但這種報警是被動式的(就是dashboards中查詢到的值超過了閥值才觸發報警),談不上好,但至少能用,可是專業性有點強,一般人還配不明白;另外就是Skywalking也有告警模塊,功能不直觀,需要在application.yml配置文件中配(配置參考官網說明),支持通過webhooks來發送notify、go-wechat、mail。看到這,我們也明白了,報警功能差異化大根本集成不到一塊,對於易用性和擴展性上來說,這塊暫時無解,除非能介入到數據層,獨立開發出一套分析報警的功能,那這個工作量就大大超過了原來的預計,失去了集成平臺的意義了。
說了這麼多,也展示一下集成後的界面效果:
1、監控模型管理
通過上傳監控模板 (監控代理的配置文件+使用說明),自動集成到telegraf、jmxtrans、skywalking agent的包中生成zip壓縮文件,以提供下載,由於下載的包中已經帶有配好的配置文件和啓動腳本及初始化配置文件的腳本。所以在遠程啓動監控代理時,就會自動配置好,並開啓監控進程(好處當然就是增強了易用性,因爲一般人是配不明白這些配置文件的)。
創建監控包來說最大的工作量還在於使用大量批處理腳本,就以Windws下創建Telegraf服務來說,需要調用SetACL修改註冊表權限(以便WMI能遠程調用服務),需要以最高權限註冊服務,所以腳本就很複雜,如下所示:
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================
:init
setlocal DisableDelayedExpansion
set cmdInvoke=1
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
REM 把需要運行的腳本放到下面
::判斷遠程註冊服務是否開啓
for /f "skip=3 tokens=4" %%i in ('sc query RemoteRegistry') do set "zt=%%i" &goto :next
:next
if /i "%zt%"=="STOPPED" (
sc config RemoteRegistry start= auto
net start RemoteRegistry
regsvr32 %SystemRoot%\system32\wbem\wbemdisp.dll
echo "start RemoteRegistry Server"
)
::獲取WMI的administrator遠程控制權限
set rootkey="HKEY_CLASSES_ROOT\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}"
if /i "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
"%~dp0SetACL\64bit\SetACL.exe" -on %rootkey% -ot reg -actn setowner -ownr "n:administrator" -rec yes -silent
if errorlevel 0 echo OK: Set Owner
"%~dp0SetACL\64bit\SetACL.exe" -on %rootkey% -ot reg -actn ace -ace "n:administrator;p:full;m:grant;i:so,sc" -op DACL:p_c -rec yes -silent
if errorlevel 0 echo OK: Set Privilege
) else (
"%~dp0SetACL\32bit\SetACL.exe" -on %rootkey% -ot reg -actn setowner -ownr "n:administrator" -rec yes -silent
if errorlevel 0 echo OK: Set Owner
"%~dp0SetACL\32bit\SetACL.exe" -on %rootkey% -ot reg -actn ace -ace "n:administrator;p:full;m:grant;i:so,sc" -op DACL:p_c -rec yes -silent
if errorlevel 0 echo OK: Set Privilege
)
set rootkey=
::創建telegraf監控服務
sc create telegraf binPath= "\"%~dp0telegraf.exe\" -config \"%~dp0telegraf.conf\""
pause
2、監控節點管理
首先就是新增或修改節點,把需要監控的節點信息配置好,而這些配置信息將會作爲同步到監控代理配置文件的依據:
然後在節點管理界面,點擊啓用或配置,相關的IP、端口、節點名稱等信息就會自動通過遠程執行腳本的方式,替換到監控代理的配置文件中,並完成代理的啓動。
啓動完後,通過監控【視圖】(配置了動態router實現鏈接)可以看到監控的結果(Grafana面板示例):
以下爲Skywalking監控面板示例(Skywalking UI做了Router和數據過濾改造,只顯示當前節點的監控數據):
再放一張炫酷一點的,這就是Skywalking的魅力:
3、監控數據管理
這塊還沒開發,思路就是通過Java連接influxdb、ES、Mysql,對監控的數據進行清理,比如監控節點刪除後,相關的關聯數據可以做個刪除操作,或者修改influxdb的數據保留策略(例如保留最近2天的數據)。
4、Vue Router配置
由於涉及鏈接到grafana(不同類型的監控配置了不同的面板)和Skywalking UI,所以需要配置Router。主要有兩種方式,一種是菜單的形式調用。比如菜單的URL配置爲http://${skywalking}/和http://${grafana}/d/PGoagxIWk/postgresql-server?orgId=1,在${skywalking}和${grafana}作爲參數變量進行替換,節選代碼如下:
// url以http[s]://開頭, 通過iframe展示
if (isURL(menuList[i].url)) {
route['path'] = `i-${menuList[i].menuId}`
route['name'] = `i-${menuList[i].menuId}`
// route['meta']['iframeUrl'] = menuList[i].url
if (menuList[i].url.match(/\$\{grafana\}/)) {
route['meta']['iframeUrl'] = menuList[i].url.replace(/\$\{grafana\}/, grafanaUrl)
} else if (menuList[i].url.match(/\$\{skywalking\}/)) {
route['meta']['iframeUrl'] = menuList[i].url.replace(/\$\{skywalking\}/, skywalkingUrl)
} else {
route['meta']['iframeUrl'] = menuList[i].url
}
} else {
try {
route['component'] = _import(`modules/${menuList[i].url}`) || null
} catch (e) {}
}
routes.push(route)
另一種是以iframe的形式,動態的調用Router:
<template>
<div><iframe :src="url" width='100%' height='760' frameborder='0' id="urlIframe"></iframe></div>
</template>
<script>
export default {
data: function () {
return {
url: this.$route.params.url
}
},
activated: function () { /* 再次調用時,更換URL */
const oIframe = document.getElementById('urlIframe')
oIframe.src = this.$route.params.url
}
}
</script>
5、一鍵啓動
爲什麼要集成,除了方便使用,還有個原因當然是爲了方便部署,無論是在linux下,還是windows下,都要求無障礙部署。
(1)要求平臺的前端niginx要自動安裝部署,自動修改配置文件,自動將dist頁面文件拷入到html目錄;windows自帶有7zip解壓zip安裝文件的組件。
(2)後端以jar服務啓動,windows下要求以JavaService.exe創建widnows服務並自啓動,另外windows下啓動服務要通過vbs等操作獲取管理員權限啓動。
(3)管理平臺的數據庫環境以mysql或postgresql ,做成一鍵部署(可以將帶初始化數據的庫文件一起打入安裝包,這樣再次安裝解壓數據庫時就不需要導入初始數據了),linux下是tar.gz的二進制安裝文件,windows下是zip綠色包文件。
(4)influxdb和grafana也是一鍵部署,基於官網的tar.gz或zip包解壓運行,可以先將初始數據打入安裝包中。
(5)skywalking官網的集成包,就帶有一鍵啓動,只需要做少量改動,將ES或tcp h2的啓動也加入到一鍵啓動中(需要加個端口啓動判斷,必須等數據庫端口啓動後,再啓動OAP服務,否則OAP服務啓動後會再次關閉)。
(6)有了一鍵啓動,還要有一鍵殺進程及卸載服務的功能。並且要避免重複啓動進程。
雖然可以按以上要求做成一鍵啓動監控平臺,但還算不上真正的一鍵部署,除非加入配置的一步步輸入提示,自動安裝JRE及環境變量等基礎環境,但這樣一來安裝包的大小將很大,對於集成系統來說,這是很難理想化的,畢竟各個模塊也都推薦分佈式部署,非要做成單機版一鍵安裝,有點本末倒置。
未完待續......(後續涉及到監控數據管理功能的開發,和整合所有監控節點的健康狀態展示,由於工作量較大,還沒能力在短期內落實)