进程监控:Prometheus+Process exporter+Grafana进程监控
容器监控 cadvisor + Prometheus+Grafana监控Docker容器
(cadvisor 指标比较多,我们在Grafana自己编辑采集的指标, 比如容器内存用这个container_memory_working_set_bytes{job="cadvisor", name="apc_boolean"}
默认的内存可能不是我们想要的,看到这个 https://blog.csdn.net/u010918487/article/details/106190764才知道的
)
主机监控 node_exporter Prometheus+Grafana 监控主机
prometheus client_golang 简单使用
Go进阶31:python 的 Prometheus Client教程
apc_boolean
gitbook 介绍普罗米的:
https://yunlzheng.gitbook.io/prometheus-book/introduction
接下来就详细介绍一下 普罗米的使用,并在最后的一个项目中使它结合 grafna 展示一些数据
总体特征
- 收集的数据是时间戳 和 可选的标签 值 以及指标 共同存储
- PromQL 自己的查询数据的 语言 类似 sql 这些
- 采集数据通过http pull
- 可以配置中间网关 push 数据,但最后 普罗米从网关 pull 数据
- 支持服务发现获取 pull 地址(当然也可以直接配置 目标机器)
- 支持 grafana 等仪表盘获取数据展示
可以看出来, 普罗米就是通过 http 采集数据, 并存储,数据展示可以被其他开源组件。
使用
- 安装
下载对应的版本
tar xvfz prometheus-*.tar.gz
cd prometheus-*
// 启动
./prometheus --config.file=prometheus.yml
// 可以编辑 prometheus.yml ,在里面配置一些数据采集的地址
配置文件有 global、rule_files和scrape_configs 三个字段
// 全局配置
global:
scrape_interval: 15s // 采集周期
evaluation_interval: 15s // 判断规则时间, 生成警报
rule_files: // 加载其他规则文件
# - "first.rules"
# - "second.rules"
scrape_configs: // 监控数据来源
- job_name: prometheus
static_configs:
- targets: ['localhost:9090']
指标类型
- Counter
单调递增的计数器, 记录比如 请求总数,任务总数这些只会增加的指标, 对于波动的数据使用 Gauge
python 实例:
pip install prometheus_client
进程重新启动时重置
from prometheus_client import Counter
c = Counter('my_failures', 'Description of counter')
c.inc() # Increment by 1
c.inc(1.6) # Increment by given value
- Gauge
记录波动的数值, 比如请求的 qps(直接客户端上报,记得天一就是在入口处计算的qps, 直接是原子累加,不用在前端计算了), 温度变化等
python:
from prometheus_client import Gauge
g = Gauge('my_inprogress_requests', 'Description of gauge')
g.inc() # 增加
g.dec(10) # 减少
g.set(4.2) # 设置到某个值
天一统计 qps:
就是一个在接口入口原子计数累积,每秒清零,其实可以把这个 qps 上报到 Gauge, 但是采集速度不是每秒的,所以还是有误差的
go func(t *time.Ticker) {
defer ticker.Stop()
for {
// 一秒打印一次统计数量
<- t.C
common.GetLogger().Error("module current qps is:", atomic.LoadInt64(&Model_rate))
httpRequestGauge.WithLabelValues("qps").Set(float64(atomic.LoadInt64(&Model_rate)))
// 清空
atomic.StoreInt64(&Model_rate, 0)
}
}(ticker)
效果:
为了便于观察, 把 label 的path 参数都改成 qps
- Histogram
直方图, 对观察结果进行采样, 通常是 请求响应时间或响应大小,就是你只管 Observe, 其他的由普罗米抽样显示。并不是全部显示,因为全部展示数据量太大。
我们也可以使用函数,查看 tp99 这些数据, 结果和 summary 计算的基本一致
histogram_quantile(0.99, http_request_histogram_bucket)
- Summary
同直方图
from prometheus_client import Summary
s = Summary('request_latency_seconds', 'Description of summary')
s.observe(4.7) # Observe 4.7 (seconds in this case)
服务接入普罗米
- 查看服务监听正不正常
http://localhost:9090/targets
go 客户端代码, 模拟某个服务,并定时请 /test 接口
我们定义了一个总请求量和每次请求的耗时 这两个指标
package main
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"math/rand"
"net/http"
"strconv"
"time"
)
// prometheus.NewCounterVec 带 Vec的可以多添加 label 参数
// 创建计数器
var httpRequestCount = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_request_count",
Help: "http request count",
},
[]string{"endpoint"},
)
// 创建Gauge
var httpRequestGauge = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "http_request_Gauge",
Help: "http request Gauge",
},
[]string{"endpoint"},
)
// 创建 summary 指标
var httpRequestSummary= prometheus.NewSummaryVec(
prometheus.SummaryOpts{ // 指标名称
Name: "http_request_summary",
Help: "http request Summary",
// 客户端计算 百分比分类, 不加这个配置就没数据
// 后面的 0.05 0.01 代表 百分比误差, 0.5 对应的是 0.05 表示 45% - 55% 的区间都可以作为目标值
// 假设某个0.5-quantile的值为120,由于设置的误差为0.05,所以120代表的真实quantile是(0.45, 0.55)范围内的某个值。
// 参考: https://cloud.tencent.com/developer/news/319419
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, // 返回五分数, 九分数, 九九分数
},
[]string{"endpoint"}, // label 列表
)
// 创建 Histogram 指标 (也可以使用 histogram_quantile(0.99, http_request_histogram_bucket) 来计算 tp99)
var httpRequestHistogram = prometheus.NewHistogramVec(
prometheus.HistogramOpts{ // 指标名称
Name: "http_request_histogram",
Help: "http request Histogram",
Buckets: prometheus.LinearBuckets(20, 20, 5), //第一个桶20起,每个桶间隔20,共5个桶。 所以20, 40, 60, 80, 100
},
[]string{"endpoint"}, // label 列表
)
// 初始化, 注册两个指标
func init() {
// 请求总数,可计算 用rate 函数计算 qps, 或者计算 label 为枚举类型的百分比, 直接算就好了
prometheus.MustRegister(httpRequestCount)
// cpu 使用率这些,直接上传 qps
prometheus.MustRegister(httpRequestGauge)
// Summary 可以分析平均耗时 (客户端计算,不确定的状态分布,可以写几个范围)
prometheus.MustRegister(httpRequestSummary)
// 直方图, 也可以分析平均耗时 (服务端计算)
prometheus.MustRegister(httpRequestHistogram)
}
func main() {
// metrics 接口,用于收集指标
http.Handle("/metrics", promhttp.Handler())
// 自测接口, 用于修改指标
http.HandleFunc("/test0", handler)
http.HandleFunc("/test1", handler)
go func() {
fmt.Println("服务启动")
err := http.ListenAndServe(":8888", nil)
if err != nil{
fmt.Println(err)
}
}()
startClient()
doneChan := make(chan struct{})
<-doneChan
}
// 自定义接口
func handler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
path := r.URL.Path
// 请求计数器, 请求路径为标签
httpRequestCount.WithLabelValues(path).Inc()
// 模拟处理不同的耗时
n := rand.Intn(100)
if n >= 95 { // 5% 耗时 100
time.Sleep(100 * time.Millisecond)
} else { // %95 耗时 50
time.Sleep(50 * time.Millisecond)
}
// 请求耗时 xx ms
elapsed := (float64)(time.Since(start) / time.Millisecond)
// 记录当前请求的耗时 Summary
httpRequestSummary.WithLabelValues(path).Observe(elapsed)
// 记录平均耗时 直方图
httpRequestHistogram.WithLabelValues(path).Observe(elapsed)
httpRequestGauge.WithLabelValues(path).Set(float64(rand.Intn(100)))
}
// 测试脚本
func startClient() {
sleepTime := 1000
// 模拟请求频率,每三十秒请求间隔设置 1s, 每两分钟设置为 0.2, 就是 0.2 高频会持续不超过 30秒
go func() {
ticker := time.NewTicker(2 * time.Minute)
for {
<-ticker.C
sleepTime = 200
<-time.After(30 * time.Second)
sleepTime = 1000
}
}()
for i := 0; i < 100; i++ {
go func() {
for {
sendRequest()
time.Sleep((time.Duration)(sleepTime) * time.Millisecond)
}
}()
}
}
func sendRequest() {
api_verson := strconv.Itoa(rand.Intn(2))
resp, err := http.Get("http://localhost:8888/test" + api_verson)
if err != nil {
log.Println(err)
return
}
resp.Body.Close()
}
查看qps 可以使用 自带函数 rate
参考: https://cjting.me/2017/03/12/use-prometheus-to-monitor-server/
怎么计算 qps, 和请求耗时, 并对接 grafana
普罗米修斯对接 grafana 前端
-
新建数据源为 普罗米,然后配置请求数据 url
-
新建一个 dashborad, 用来展示数据
-
展示的数据是根据label 分类展示的
当然也可以在一个 dashbroad 展示几个 查询语句,但是建议只展示同一个 指标类型,不然坐标轴不统一
-
保存dashboad
-
四种数据类型效果
可以拖动 panel, 摆放合适的位置, 想要看具体的某个 label 数据,直接点击 tag 就好了。
普罗米修斯告警
告警内容:
- 告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容
- 告警规则:告警规则实际上主要由 PromQL 进行定义,其实际意义是当表达式(PromQL)查询结果持续多长时间(During)后出发告警
- 模板变量
通过value则可以获取当前PromQL表达式计算的样本值(就是判断是不是告警的值)
比如:
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
- 设置告警规则
rule_files:
- /etc/prometheus/rules/*.rules
我们可以设置多个告警文件, 普罗米会默认一分钟(通过 evaluation_interval 设置)跑所以的告警语句
- 告警状态
样本值为1表示当前告警处于活动状态(pending 就是触发了,但是可能设置持续一分钟才告警,所以为等待状态 或者firing 已经发出告警了),当告警从活动状态转换为非活动状态时,样本值则为0。
- Alertmanager 接受普罗米的告警
从普罗米官网 下载 alertmanage 或 docker 安装。
// alertmanager.yml 也有这个配置文件
./alertmanager 启动
- 关联Prometheus与Alertmanager
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
- Alertmanager配置概述
略 就是配置一些邮件这些。实际操作的时候在写
一些问题
如何将日志输入?
简短的回答:不要!改用ELK 堆栈 之类的东西
更长的答案:Prometheus 是一个收集和处理指标的系统,而不是事件记录系统如何选择使用哪种数据格式呢
先说几个简单的:
qps 可以用 counter 结合rate/irate进行计算
在线人数,或者服务状态, 温度变化用 Gauge关于 Summary 里面参数 Objectives 的设置
参考 https://cloud.tencent.com/developer/news/319419
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, // 返回五分数, 九分数, 九九分数
主要是 0.5: 0.05 说明是 50% 的数据, 其实是 45% - 50% 中的一个数据, 并不能精确到 50% 整,因为数据太多,计算精确到话,太耗性能。关心的 0.99 可以计算准确一点。
- 关于grafana 模板定义
定义模板是为了解决 硬编码的问题(类似组件)
https://yunlzheng.gitbook.io/prometheus-book/part-ii-prometheus-jin-jie/grafana/templating
https://www.mianshigee.com/tutorial/prometheus-book/grafana-templating.md
怎么导出自己编辑好的模板:
可以使用 label_values({job="$job"}, instance) 进行快速筛选某个属性
比如上查询了 dfir_service_time_cost_count 这个指标, 所有job的可选值, 简单的正则分组匹配即可
dfir_service_time_cost_count{instance="91yxlv2.tianyi.iflytekauto.cn:80", job="ugc-0-gray", path="/ugc/run", service="UGC"}
如果把字符串拼接到字符串,请用
${xx}
而不能直接 $xx
为啥用 “=~” 来指定变量呢,这是因为菜单 select 可以是多选,值会是 xx|xx|xx 的格式, ~ 是正则匹配,不加会匹配不到的
变量的值可以支持单选或者多选,当对接Prometheus时,Grafana会自动将$node的值格式化为如“host1|host2|host3”的形式。配合使用PromQL的标签正则匹配“=~”,通过动态改变PromQL从而实现基于标签快速对时间序列进行过滤。
关于如何监控主机 cpu 内存等
node_exporter 用普罗米开源采集工具, 启动就好了
https://cloud.tencent.com/developer/article/1808172-
grafana 如何新建不同的用户以及设置他们对dashboard 的权限
https://www.modb.pro/db/499351
左下角从组织开始,新建组织,新建用户等,以及设置他们的角色 (每个组织默认会有当前的 admin 用户,并且就算 admin自己也删不掉是新建 组织的超级管理员)
admin 用户可以管理所有的组织和所有的dashboard 以及 用户
每个组织下可以有单独的管理员和可编辑权限和只读权限