GO监控方案-prometheus
2022-10-24 21:52:26    564    0    0
weibo-007

整体架构

安装prometheus

mac安装方式

1.下载安装包

https://prometheus.io/download/

 

2.解压运行

解压后,运行./prometheus --config.file=prometheus.yml

这里mac系统可能会碰到无法打开的问题,按照如下操作之后,再次运行命令

a.点击屏幕左上角的苹果图标,选择菜单:系统偏好设置...。
b.打开系统偏好设置界面,点击"安全性与隐私"->"通用"。
c.在窗口底部会看到:已阻止使用“XXX”,因为来自身份不明的开发者。点击后面的"仍要打开"按钮

 

3.访问

浏览器地址输入:http://localhost:9090/,即可访问

使用prometheus监控go应用

默认监控项

在go项目中引入prometheus之后,默认已经有监控项了,我们可以在prometheus的监控面板中看到,比如下面的例子

1)编写一个最简go应用

package main

import (
	"net/http"

	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
	http.Handle("/metrics", promhttp.Handler()) //暴露 metrics 指标
	http.ListenAndServe(":8091", nil) //启动Server
}

 

2)查看默认指标

2.1. 运行上面的go程序

go run main.go

2.2 浏览器访问http://localhost:8091/metrics 然后查看默认指标输出

这里我们关注promhttp_metric_handler_requests_total指标,表示http访问量,每次刷新这个指标会+1。


3)将go应用节点添加到prometheus的prometheus.yml配置

追加配置到prometheus.yml中

  # 这里新增一个监控Go应用节点
  - job_name: "gomonitor"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:8091"]


4)重启promethueus

./prometheus --config.file=prometheus.yml

 

5)查看prometheus监控面板

点击Execute可以看到监控面板的http访问趋势

prometheus术语解释

指标名称(metric name)

表示了被测系统的一般特征,即一个可以度量的指标

它采用了普遍的名称来描述一个时间序列,例如

1)promhttp_metric_handler_requests_total 表示请求总数

2)go_goroutines go运行的协程数量

标签(label)

当指标名称需要细化的时候,可以使用标签进行扩展,相同指标名称的任何给定标签组合标识该指标的特定维度实例

例如:

1)promhttp_metric_handler_requests_total{method=POST} 表示有POST标签的请求总数

2)promhttp_metric_handler_requests_total{status=200} 表示有状态码为200标签的请求总数

样本(sample)

按照某个时序以时间维度采集的数据称为样本,实际的时间序列,每个序列包括一个float64的值和一个毫秒级的unix时间戳,本质上属于单值模型,例如:

1)在某个采集的时刻,指标输出为"promhttp_metric_handler_requests_total{code="200"} 126" 表示这一刻的样本值为126

 

整个prometheus的数据存储可以用下面的模型来表示

1)其中横轴是时间,纵轴是时间线,时间线就是指标名称和一组标签的组合

2)区域内每个点就是数据点

3)在同一时刻,每条时间线只会产生一个数据点,但同时会有多条时间线产生数据

自定义监控项

很多情况下prometheus提供的go sdk并不能很好的满足我们业务上的应用,所以我们还有自定义监控指标的需求。

prometheus提供了四大度量指标

Counter (计数器)

描述

Counter 类型代表一个累积的指标数据,其单调递增,只增不减。在应用场景中,像是请求次数、错误数量等等,就非常适合用 Counter 来做指标类型,另外 Counter 类型,只有在被采集端重新启动时才会归零。

常用方法

方法名作用
Inc将计数器递增1
Add (float64)将给定添加计数器中,小于0报错

应用例子

package main

import (
	"net/http"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {

	//申明一个Counter
	var AccessCounter = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "http_server_requests_bucket",
		},
		[]string{"path"},
	)

	//将申明的Counter注册
	prometheus.MustRegister(AccessCounter)

	//这里是业务逻辑,假设有一个获取用户信息接口
	http.HandleFunc("/getUser", func(w http.ResponseWriter, r *http.Request) {
		//这里针对接口访问量进行递增,这里简单起见,写死了path
		AccessCounter.With(prometheus.Labels{
            "path":   "getUser",
        }).Add(1)
	})
	

	http.Handle("/metrics", promhttp.Handler()) //暴露 metrics 指标
	http.ListenAndServe(":8091", nil) //启动Server
}

启动之后,先访问接口使得指标递增

http://localhost:8091/getUser

然后再访问prometheus监控界面,这条曲线永远是递增的

 

Gauge (仪表盘)

描述

Gauge 类型代表一个可以任意变化的指标数据,其可增可减。在应用场景中,像是 Go 应用程序运行时的 Goroutine 的数量就可以用该类型来表示,在系统中统计 CPU、Memory 等等时很常见,而在业务场景中,业务队列的数量也可以用 Gauge 来统计,实时观察队列数量,及时发现堆积情况,因为其是浮动的数值,并非固定的,侧重于反馈当前的情况

常用方法

方法名作用
Set(float64)将仪表设置为任意值
Inc()将仪表增加 1
Dec()将仪表减少 1
Add(float64)将给定值添加到仪表,该值如果为负数,那么将导致仪表值减少
Sub(float64)从仪表中减去给定值,该值如果为负数,那么将导致仪表值增加
SetToCurrentTime()将仪表设置为当前Unix时间(以秒为单位)

应用例子

package main

import (
	"fmt"
	"time"
	"net/http"
	"math/rand"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {

	//申明一个Counter
	var QueueGauge = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "queue_num_total",
		},
		[]string{"name"},
	)

	//将申明的Counter注册
	prometheus.MustRegister(QueueGauge)

	//这里是业务逻辑,设置队列长度的接口
	http.HandleFunc("/queueNum", func(w http.ResponseWriter, r *http.Request) {
		rand.Seed(time.Now().UnixNano())
		num := rand.Intn(81)//这里模拟队列长度
		QueueGauge.With(prometheus.Labels{
            "name":"queue_order",
        }).Set(float64(num))
		fmt.Println(num)
	})
	

	http.Handle("/metrics", promhttp.Handler()) //暴露 metrics 指标
	http.ListenAndServe(":8091", nil) //启动Server
}

启动之后,先访问接口使得指标随机

http://localhost:8091/queueNum

然后再访问prometheus监控界面,这条曲线永远是有增有减的

Histogram(累积直方图)

描述

Histogram 类型将会在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等等),并将其计入可配置的存储桶(bucket)中,后续可通过指定区间筛选样本,也可以统计样本总数。

Histogram 类型在应用场景中非常的常用,因为其代表的就是分组区间的统计,而在分布式场景盛行的现在,链路追踪系统是必不可少的,那么针对不同的链路的分析统计就非常的有必要,例如像是对 RPC、SQL、HTTP、Redis 的 P90、P95、P99 进行计算统计,并且更进一步的做告警,就能够及时的发现应用链路缓慢,进而发现和减少第三方系统的影响。
注意:这种指标只适合统计桶内数量,不能计算分位耗时。例如可以用来统计统计延迟在 0~10ms 之间的请求数有多少而 10~20ms 之间的请求数又有多少
但是:有可以将直方图拟合成连续的直线,然后估算分位耗时,但这并不准确。
有一点可以:做SLA承诺的时候,比如保证99%的请求在200ms内范围,90%的请求在300ms内返回,那可以设置包含200ms和300ms的区间bucket

数据模型

1)这里的bucket是设置的上下限,比如落在区间[0.1-0.2]的样本数量,但是这里有一个区别,后一个区间会累加上前一个区间

2)统计分位数的时候,其实是拟合的区间进行统计的,如果bucket区间设置合理,这个值具备参考性,否责误差很大

常用方法

方法名作用
Observe(float64)将一个观察值添加到直方图。

应用例子

package main

import (
	"fmt"
	"time"
	"net/http"
	"math/rand"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {

	//申明
	var HttpHistogram = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name: "http_durations_histogram_seconds",
			Buckets: []float64{0.2, 0.5, 1, 2, 5, 10, 30},
		},
		[]string{"path"},
	)

	//将申明的注册
	prometheus.MustRegister(HttpHistogram)

	//这里是业务逻辑,设置队列长度的接口
	http.HandleFunc("/queueNum", func(w http.ResponseWriter, r *http.Request) {
		rand.Seed(time.Now().UnixNano())
		num := rand.Intn(30)
		HttpHistogram.With(prometheus.Labels{
            "path": "/user/info",
        }).Observe(float64(num))
		fmt.Println(num)
	})
	

	http.Handle("/metrics", promhttp.Handler()) //暴露 metrics 指标
	http.ListenAndServe(":8091", nil) //启动Server
}

 启动之后,先访问接口使得指标随机

http://localhost:8091/queueNum

Summary(摘要)

描述

Summary 类型将会在一段时间范围内对数据进行采样,但是与 Histogram 类型不同的是 Summary 类型将会存储分位数(在客户端进行计算),而不像 Histogram 类型,根据所设置的区间情况统计存储。提供三种摘要指标: 样本值的分位数分布情况,所有样本值的大小总和,样本总数
注意,这种指标可以用来计算样本值的分位数分布情况,就是我们常说的分位耗时可以用这种指标计算

常用方法

方法名作用
Observe(float64)将一个观察值添加到直方图。

应用例子

package main

import (
	"fmt"
	"time"
	"net/http"
	"math/rand"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {

	//申明
	var HttpDurations = prometheus.NewSummaryVec(
		prometheus.SummaryOpts{
			Name:       "http_durations_seconds",
			Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
		},
		[]string{"path"},
	)

	//将申明的注册
	prometheus.MustRegister(HttpDurations)

	//这里是业务逻辑,设置队列长度的接口
	http.HandleFunc("/queueNum", func(w http.ResponseWriter, r *http.Request) {
		rand.Seed(time.Now().UnixNano())
		num := rand.Intn(30)
		HttpDurations.With(prometheus.Labels{"path": "/user/phone"}).Observe(float64(num))
		fmt.Println(num)
	})
	

	http.Handle("/metrics", promhttp.Handler()) //暴露 metrics 指标
	http.ListenAndServe(":8091", nil) //启动Server
}

启动之后,先访问接口使得指标随机

http://localhost:8091/queueNum

写在最后

最后,一般公司架构都集成了prometheus,无需自己单独搭建这一套,包括监控MySQL,Redis社区内也有非常好的解决方案。作为业务开发,将花费精力放在通用prometheus指标没有覆盖的地方,然后建立业务专属的监控指标

 

 

 

Pre: DDD系列-领域建模

Next: DDD系列-建模设计全流程

564
Sign in to leave a comment.
No Leanote account? Sign up now.
0 comments
Table of content