如何監控 Go Runtime
文章來自於 http://blog.helongfei.com/2019/%E7%9B%91%E6%8E%A7-go-runtime/,也可以閱讀原文閱讀。
Go 通常作爲守護進程存在,若我們不做任何監控,放任其「自由」的使用資源,那有可能會發現意外情況,比如「Goroutine 泄露」。那我們應該如何監控,又要監控哪些指標呢?
監控指標
監控的核心是監控指標,「有用」的指標纔是有意義,那 Go 有哪些有意義的指標呢?
我認爲只要監控go runtime
相關的指標就行,整體分爲兩大類:
-
CPU:goroutine、cgo
-
內存:gc、heap、stack
監控架構
既然確定了監控指標,那如何監控呢?這裏要感謝 Brian Hatfield 開源的 go-runtime-metrics[1],我們可以利用它快速的搭建監控系統。
整體架構如下:
Go runtime 監控架構圖
由圖可知,我們使用了Grafana
,Graphite
,Statsd
;其中Statsd
是和運行程序部署在一起的,默認是 10s 上報一次,對性能的影響不是太大,真的出現瓶頸的時候,可以再抽離;Graphite
是包含圖表的;這裏使用的是 Grafana
集成 Graphite
。
Go-runtime-metric
https://github.com/bmhatfield/go-runtime-metrics
工作原理:
-
程序啓動後,開啓一個
goroutine
採集上報metric
,數據收集使用statsd
,傳輸協議採用UDP
-
在
main
函數中使用flag.Parse()
纔會打開採集上報(上報服務地址等通過命令行參數修改) -
採樣率 100%,且不可修改(可以自己 fork 後修改)
-
上報間隔 10s,可通過命令行
--pause
修改 -
使用的 metric type 是
Gauges
-
所有的採集項都是通過
runtime
包完成的;統計mem
時,會觸發STW
(若關心性能,建議關閉統計mem
)
可用參數:
--statsd=localhost:8125 # Statsd host:port
--metric-prefix # Metric prefix path;用於區分機器/應用等
--pause=10 # 上報間隔;default 10s
--publish-runtime-stats=true # 是否採集 go runtime;採集總開關
--cpu # 是否採集 CPU
--mem # 是否採集 mem
--gc # 是否採集 GC (必須開啓 --mem)
Statsd
https://github.com/statsd/statsd
基於 node.js 實現,用於收集 metric 數據,支持 UDP、TCP 協議,默認每 10s 向後端發送一次數據,支持集羣部署。支持的 metric type[2] 有 Counting、Sampling、Timing、Gauges。支持多種 backend[3],內置三個:Graphite
,Console
,Repeater
,第三方見文檔。
啓動前使用run_tests.js
檢查下環境等問題。使用起來很簡單,主要是兩個配置文件:exampleConfig.js
、exampleProxyConfig.js
,前者用於單機部署,後者用於集羣部署;詳細配置含義見文件內容註釋。
使用Graphite
示例:
// 單機部署
{
graphitePort: 2003,
graphiteHost: "localhost",
port: 8125,
server: "./servers/udp", debug: true,
backends: [ "./backends/console", "./backends/graphite" ]
}
Graphite
http://graphiteapp.org/
Graphite 主要作用是保存 metric 數據,並將其可視化。內置三個組件:
-
carbon:監聽時間序列數據(守護進程)
-
whisper:存儲時間序列數據(數據存儲 - 類似 RRD)
-
graphite-webapp:渲染時間序列數據,提供 Web & API(Web 應用)
架構圖如下:
graphite 架構圖
Carbon
Carbon 主要是監聽並處理 metric 。
配置
https://graphite.readthedocs.io/en/latest/config-carbon.html
包含多個 conf(默認在 /opt/graphite/conf):
-
carbon.conf 主要是三個 sectoion:[cache] 緩存、[relay] 轉發、[aggregator] 聚合
-
storage-schemas.conf 主要是存儲週期設置。修改後不會立即生效,需要執行下
whisper-resize.py
[apache_busyWorkers] pattern = ^servers\.www.*\.workers\.busyWorkers$ # 15s 一個點,存 7 天;1m 一個點,存 21 天... retentions = 15s:7d,1m:21d,15m:5y
-
storage-aggregation.conf 主要是多個相同 metric 聚合 metric,修改後不會立即生效,需要執行
whisper-set-aggregation-method.py *.wsp <method>
[all_min] pattern = \.min$ # 上一個 retention level 至少含有下一個 level 的 10% 的值 xFilesFactor = 0.1 # 聚合方法 aggregationMethod = min
-
relay-rules.conf 主要是轉發數據
[example] pattern = ^mydata\.foo\..+ servers = 10.1.2.3, 10.1.2.4:2004, myserver.mydomain.com
-
aggregation-rules.conf 主要是根據 rule、method,對 metric 進行聚合操作
output_template (frequency) = method input_pattern
-
rewrite-rules.conf 根據 rule 對 metric 進行重命名
regex-pattern = replacement-text
-
whitelist.conf 設置 metric 白名單
-
blacklist.conf 設置 metric 黑名單
啓動
單機
https://graphite.readthedocs.io/en/latest/admin-carbon.html
使用 carbon-cache.py
,相關配置:carbon.conf、storage-schemas.conf
/opt/graphite/bin/carbon-cache.py start
若有性能問題,可以在運行carbon-cache.py
之前使用carbon-aggregator.py
,對數據進行聚合,減少數據量。相關配置:carbon.conf、aggregation-rules.conf
集羣
https://graphite.readthedocs.io/en/latest/carbon-daemons.html
使用 carbon-relay.py
,主要作用是複製和分片。相關配置:carbon.conf、relay-rules.conf 也可以使用carbon-aggregator-cache.py
, 它合併了carbon-aggregator.py
和carbon-cache.py
兩個腳本,相關配置:carbon.conf、relay-rules.conf、aggregation-rules.conf
Graphite-web
使用 Django 開發。
配置
https://graphite.readthedocs.io/en/latest/config-local-settings.html
這裏的 database 主要是存儲用戶、dashboard 等信息。默認使用 SQLite。
啓動
https://graphite.readthedocs.io/en/latest/config-webapp.html
配置 nginx + gunicorn
Whisper
https://graphite.readthedocs.io/en/latest/whisper.html
存儲時間序列數據,類似 RRD,一個環形數據庫。
部署
本地學習環境安裝,非高性能版安裝。
安裝步驟
-
安裝 Graphite + statsd 使用 Docker 安裝,推薦使用 Graphite 官方的 docker repo[4],包含 Graphite & statsd
-
安裝 Grafana
-
Go 工程代碼中添加
github.com/bmhatfield/go-runtime-metrics
使用示例:
package main
import (
"flag"
"log"
"net/http"
"os"
_ "github.com/bmhatfield/go-runtime-metrics"
)
func main() {
// 打開採集
flag.Parse()
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
srv := &http.Server{
Addr: ":8000", // Normally ":443"
Handler: http.FileServer(http.Dir(cwd)),
}
log.Fatal(srv.ListenAndServe())
}
參考資料
-
Graphite[5]
-
Statsd[6]
-
Go-runtime-metric[7]
參考資料
[1]
go-runtime-metrics: https://github.com/bmhatfield/go-runtime-metrics
[2]
metric type: https://github.com/statsd/statsd/blob/master/docs/metric_types.md
[3]
backend: https://github.com/statsd/statsd/blob/master/docs/backend.md
[4]
docker repo: https://github.com/graphite-project/docker-graphite-statsd
[5]
Graphite: http://graphiteapp.org/
[6]
Statsd: https://github.com/statsd/statsd
[7]
Go-runtime-metric: https://github.com/bmhatfield/go-runtime-metrics
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/67ChnjkM3QNmMuNvck28og