背景 : Prometheus 是近年来最盛行的开源监控框架, 其功能强大且易于运用, 具有各种主流后端言语(Java/Go/Python/Node.js等)与各种场景(如web handler/ k8s/Nginx/MySQL等)的客户端, 并自带图形化显示页面。共享一个快速入门Prometheus 的教程, 完成一个极简的, 后端开发需求特别重视的 QPS 监控。
Docker 布置 Prometheus
命令行输入
docker run -d --name prometheus-node1 -p 9090:9090 bitnami/prometheus:latest
这条命令会创建一个名为 prometheus-node1 的容器, 运用 bitnami/prometheus:latest 的镜像, 宿主机的 9090 端口与容器内的9090端口相通。
修正 prometheus 装备文件
docker cp prometheus-node1:/opt/bitnami/prometheus/conf/prometheus.yml prometheus.yml
这将 prometheus-node1 容器内的 prometheus.yml 装备文件复制出来, 大约长这样:
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['localhost:9090']
简单看看这个装备文件里边最重要的两个装备。先看 global 下面的两个装备项, scrape_interval: 15 s 表明 每15秒获取一次监控指标(prometheus 中叫 target), evaluation_interval: 15s 表明 每15秒履行一次 rules。 scrape_configs 直接界说了监控的 target. job_name 为 这个 target的姓名, static_configs 下面的 tartgets 直接指出了监控的 IP:端口。剩余的装备留给大家自己去学习,出于快速上手 Prometheus的目的,我就不细讲了。
咱们下面修正一下 targets 装备, 变成这样:
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['172.17.0.2:20001'] # 需求监控的 IP:端口
咱们修正了 targets 装备, 将他修正成需求监控的 IP:端口, 这儿的 172.17.0.2 为别的一个 docker 容器的 IP地址(待会会将), 20001 为要监控的端口(待会会将)
然后将修正后的 装备文件放回 docker 容器
docker cp prometheus.yml prometheus-node1:/opt/bitnami/prometheus/conf/prometheus.yml
再重启 容器
docker restart prometheus-node1
写一个 Web Handler 和 Web Client
创建一个 prometheus_demo 目录, 命令行输入
go mod init prometheus_demo
go mod tidy
文件目录如下:
-- prometheus_demo
-- go.mod
-- main.go
-- client
--- client.go
其间main.go 为 server 端, client.go 为客户端
其间 main.go 如下:
package main
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"net/http"
"time"
)
// 只可添加的一个计数器
var req_counter_vec = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "req_counter_vec",
Help: "request counter vector",
},
[]string{"endpoint"},
)
func main() {
prometheus.MustRegister(req_counter_vec)
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/hello", HelloHandler)
errChan := make(chan error)
go func() {
errChan <- http.ListenAndServe(":20001", nil)
}()
err := <-errChan
if err != nil {
fmt.Println("Hello server stop running.")
}
}
func HelloHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
req_counter_vec.WithLabelValues(path).Inc()
time.Sleep(100 * time.Millisecond)
}
服务端比较简单, 界说了 一个 counter vector, 里边装的是prometheus 四种数据类型的 Counter。Name 为 vector 的 姓名, help 为具体的解说, 都能够自取。[]string{“endpoint”} 表明以 endpoint 进行区分 vector 内不同的 counter。这就比如一个数组, 用 索引0,1,2 区分数组内的不同元素。
Counter 正如我注释里边写的, 便是一个计数器, 一次只能添加1, 比如每次来一个恳求, 那么就添加1。与 Counter 相对的是 Prometheus 的四种数据类型中的 Gauge。 Gauge 可加可减。数据类型 name 为变量姓名, help 为变量具体 解说, 随后将这个变量注册一下, 以便被 prometheus 监控到。当然还有别的两种用于直方图的 数据类型 Histogram 和 Summary, 我就不细说了。
随后界说了一个简单的 web handler, 里边干了两件事, 一件是记载将 counter 加 1, withLabelValues 便是就和方才的 endpoint 相对应, 相当于标记一下这个 vector 中的 哪一个 counter 加一。 另一件工作便是休眠100ms, 不至于太快完毕不利于调查。
client.go 如下
package main
import (
"log"
"net/http"
"sync"
"time"
)
func main() {
for {
wg := sync.WaitGroup{}
for i := 0; i < 50; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
resp, err := http.Get("http://localhost:20001/hello")
if err != nil {
log.Println(err)
return
}
resp.Body.Close()
}(i)
}
wg.Wait()
time.Sleep(5 * time.Second)
}
}
客户端就更简单了, 死循环里边开50个 go routine 不断发恳求。
随后将 prometheus_demo 文件布置到 docker 中, 怎么在 docker 中搭建 go 开发环境能够参阅我的另一篇 文章:保姆级从0到1解说go长途开发环境搭建(从Docker安装到运用Goland长途布置和调试)。
然后在docker容器中 prometheus_demo 目录 和 prometheus_demo/client 目录下 分别运用下面两个命令运转服务端和客户端
go run main.go
go run client.go
翻开 Prometheus Web 界面
在宿主机上用浏览器翻开 http://localhost:9090/targets?search= 假如能够调查到下面这样, 阐明 prometheus 布置成功。
注意,上面这幅图一定要发动 prometheus_demo 的 main.go 才干调查得到, 由于 prometheus 监控 20001 端口, 假如 server 端没发动, prometheus 当然啥都监控不到。
下面来看怎么监控 QPS, 在宿主机上用浏览器翻开, http://localhost:9090/graph
然后在放大镜周围的框框内输入下面这一串指令
rate(req_counter_vec{endpoint="/hello"}[15s])
再点击 graph 应该看到下面这样相似的图片
解说一下, rate(req_counter_vec{endpoint=”/hello”}[15s]) 这句指令是什么意思。 req_counter_vec 便是之前界说的装 counter 的 vector, {endpoint=”/hello”} 也便是 HelloHandler 里边记载恳求次数的 那个counter, rate 接 [15s] 表明每15秒(和 装备文件里边的15秒保持一致)记载一下 counter 的变化情况(由于 counter只能添加, 所以变化为一个 非负数), 总恳求次数除以时刻段, 便是一个范围内的 QPS。咱们这儿并不是1秒, 而是15秒, 也就能够近似看作 QPS。
假如有同学发现没有图形出现, 显示 empty query result, 可能是北京时刻和标准时刻不同步, 能够勾选 use local time, 或许 调整一 图形界面的窗口时刻(我图片上的 5m 和 2022-12-27 20:14:02 那里) 。
还有点同学出现的不是直方图而是一个个小的线段, 这是由于图形的不同展现方式的原因, 能够 点一下 Hide Exemplars 左边的两个小图标。
巨人的膀子
yunlzheng.gitbook.io/prometheus-…
hub.docker.com/r/bitnami/p…
/post/707865…
cjting.me/2017/03/12/…