0x00 概述
當 Prometheus 有配置文件修改,我們可以采用 Prometheus 提供的熱更新方法實現在不停服務的情況下實現配置文件的重新加載。
0x01 熱更新
熱更新加載方法有兩種:
#1. kill -HUP pid #2. curl -X POST http://IP/-/reload
當你采用以上任一方式執行 reload 成功的時候,將在 promtheus log 中看到如下信息:
如果因為配置信息填寫不正確導致更新失敗,將看到類似信息:
ERRO[0161] Error reloading config: couldn't load configuration (-config.file=prometheus.yml): unknown fields in scrape_config: job_nae source=main.go:146
提示:
- 我個人更傾向於采用 curl -X POST 的方式,因為每次 reload 過后, pid 會改變,使用 kill 方式需要找到當前進程號。
- 從 2.0 開始,hot reload 功能是默認關閉的,如需開啟,需要在啟動 Prometheus 的時候,添加
--web.enable-lifecycle
參數。
0x02 熱更新源碼對比
下面我們再來探討下這兩種方式內部實現原理。
第一種:通過 kill 命令的 HUP (hang up) 參數實現:
首先 Prometheus 在 cmd/promethteus/main.go
中實現了對進程系統調用監聽,如果收到 syscall.SIGHUP 信號,將執行 reloadConfig 函數。
代碼類似:
hup := make(chan os.Signal) signal.Notify(hup, syscall.SIGHUP) go func() { for { select { case <-hup: if err := reloadConfig(cfg.configFile, reloadables...); err != nil { log.Errorf("Error reloading config: %s", err) } } } }()
第二種:通過 web 模塊的 /-/reload
請求實現:
- 首先 Prometheus 在 web(web/web.go) 模塊中注冊了一個 POST 的 http 請求
/-/reload
, 它的 handler 是web.reload
函數,該函數主要向web.reloadCh
chan 里面發送一個error
。 - 在 Prometheus 的
cmd/promethteus/main.go
中有個單獨的 goroutine 來監聽web.reloadCh
,當接受到新值的時候會執行 reloadConfig 函數。
代碼類似:
hupReady := make(chan bool) go func() { <-hupReady for { select { case rc := <-webHandler.Reload(): if err := reloadConfig(cfg.configFile, reloadables...); err != nil { log.Errorf("Error reloading config: %s", err) rc <- err } else { rc <- nil } } } }()
Prometheus 內部提供了成熟的 hot reload 方案,這大大方便配置文件的修改和重新加載,在 Prometheus 生態中,很多 Exporter 也采用類似約定的實現方式。
0x03 參考