一、基本概念
Prometheus是由golang语言开发的一套开源的监控、报警、时间序列数据库的组合,是一款基于时序数据库的开源监控告警系统。
时间序列数据库:时间序列数据库(Time Serires Database , TSDB)不同于传统的关系型数据库。传统数据库更侧重于事务处理和关系型数据的存储,时间序列数据库更关注时间序列数据的处理,这类数据通常具有时间戳,如设备检测数据、传感器读数或系统日志等。
二、基本原理
Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应HTTP接口就可以接入监控。不需要任何SDK或者其他集成过程。(SDK,Software Development Kit,软件开发工具包)
输出被监控组件信息的HTTP接口被叫做exporter,目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(磁盘、内存、cpu、网络等等)
Nginx:一个高性能的HTTP和反向代理的服务器。反向代理服务器是一种服务器,位于客户端与后端之间,是一个中间人的角色。它可以将请求转发到一个或多个后端服务器上
隐藏服务器:位于客户端与后端服务器直接,客户端只能直接访问Nginx,看不到后端服务器的细节实现,可以很好的保护后端服务器免受直接访问和潜在的攻击;
负载均衡:将请求转发到多个后端服务器上,可以实现负载均衡;
缓存静态内容、处理SSL/TLS加密和证书的管理、压缩和优化.......
使用场景:
Varnish:适用于需要强大的 HTTP 缓存解决方案
HAProxy:适用于需要一个多功能的负载均衡器
Nginx:适用于需要一个既能处理静态内容也能作为反向代理的服务器,Nginx 是一个流行的选择。
Nginx应用:
前后端分离:在现代 Web 开发中,Nginx 和 Vue 可以共同工作在一个前后端分离的架构中。Nginx 作为服务器端技术,处理静态资源的提供和请求的转发,而 Vue 作为前端技术,构建用户界面和处理用户交互。
部署:Vue 应用通常需要部署到一个 Web 服务器上,Nginx 可以作为这个服务器,提供 Vue 应用的静态文件(如 JavaScript、CSS、图片等)。
性能优化:Nginx 可以配置为 Vue 应用提供服务,包括缓存、压缩、SSL 终端等,以提高应用的性能和安全性。
路由:虽然 Vue 有自己的前端路由系统(Vue Router),但 Nginx 也可以配置 URL 重写规则,以支持 SEO 或处理 API 请求。
三、基础架构
Prometheus主要由以下几部分组成:
1、Prometheus server
收集和存储时间序列数据。是服务核心组件,采用pull的方式主动手机监控数据,通过http协议传输,并存储时间序列数据。
Prometheus server 由三部分组成:
Retrieval:获取监控数据
TSDB:时间序列数据库,用来处理时间序列数据库的软件
HTTP server:为告警和出图提供查询接口
2、Push Gatway
类似中转站,因为Prometheus 的server端只能通过 pull 来获取数据,但是有的节点可能只能使用push的方式推送数据,因此就需要一个中转站。目标主机可以使用短期任务的方式将数据push到 Push Gatway上,然后再有Prometheus server统一从 Push Gatway上拉取数据。
3、Service Discovery
服务发现,用来动态的发现待监控的Target(目标主机/目的地址)。它可以通过第三方提供的接口,由Prometheus查询到需要监控的Target列表,然后轮询这些Target来获取监控数据。
4、Alertmanager
独立的告警模块。当Prometheus server端收到告警alert之后,就由Alertmanager进行去重、分组、并路由到相应的接收方,发生报警。
由Prometheus server基于用户提供的告警规则周期性计算生成一个告警指示,Alertmanager收到这个指示后,就按照指示基于用户定义的告警路由向告警接收对象发送告警信息。
四、工作流程
① Prometheus以 Prometheus server为核心,用于收集和存储时间序列数据。Prometheus server会定期从配置好的jobs或者exporters中拉取数据,或者通过Push Gatway把采集到的数据拉取到Prometheus server中。
② Prometheus server拉取到数据后,把数据存储到TSDB或者通过 TSDB 存储到本地 HHD(硬盘驱动器)/SSD(固态硬盘)中。此时已经有了监控数据,可以使用内置的PromQL进行查询。
③ Prometheus server存储好数据后,通过Alertmanager推送告警。
④ Grafana 可接入Prometheus 数据源,把监控数据以图形化形式展示出。
五、PromQL查询语言
1、基本用法
启动Prometheus服务器后,并打开http://localhost:19090/graph地址。在查询框中输入:prometheus_http_requests_total,并点击执行。
查询出所有指标名为prometheus_http_requests_total的数据。
2、完全匹配
PromQL支持使用 = 和 != 两种完全匹配模式。
查询code不等于200的数据
prometheus_http_requests_total{code!=“200”}
3、正则匹配
PromQL可以使用正则表达式作为匹配条件,并且可以使用多个匹配条件。
正向匹配:label = ~ regx ,表示选择那些标签符合正则表达式定义的时间序列;
反向匹配:label !~ regx ,进行排除。
查询在prometheus_http_request_total指标中,handler标签以/api/v1 开头的数据。
prometheus_http_requests_total{handler=~"/api/v1/.*"}
4、范围查询
上面的数据中,同一个指标同一标签只会返回一条数据,这样的表达式称为瞬间向量表达式,而返回的结果为瞬间向量。
若想查询一段时间的样本数据,则要用到区间向量表达式,查询出来的数据位区间向量。
查询最近五分钟内的所有样本数据。
prometheus_http_requests_total{}[5m]
除了m分钟以外,还有:
- s - 秒
- m - 分钟
- h - 小时
- d - 天
- w - 周
- y - 年
5、时间位移操作
以上操作都是基于当前时间,如果要查询五分钟以前的瞬时样本数据,或者昨天一天之内的样本数据,就要使用时间位移操作,使用关键字 offset。
查询5分钟之前的瞬时数据:
prometheus_http_request_total{} offset 5m
查询昨天一天之内的数据:
假如现在是2024-09-03 00:00:00,那么这个表达式查出来的数据就是:2024-09-01 至 2024-09-02 的数据
prometheus_http_request_total{}[1d] offset 1d
6、聚合操作
使用聚合函数,对查询的数据进行聚合操作。
计算一种有几条数据:
count(prometheus_http_request_total)
计算所有value的总和:
sum(prometheus_http_request_total)
sum的数值有误差,因为两次查询有时间间隔,某些记录的数值发生了变化。
7、标量
在PromQL中,标量是一个浮点型的数字值,没有时序。例如:10
在进行聚合操作时,返回的数据类型依然是瞬时向量。可以通过内置函数scalar()将单个瞬时向量转换为标量。
scalar(sum(prometheus_http_request_total))
8、字符串
在PromQL中,字符串就是一个简单的字符串值。若直接使用字符串作为表达式,则直接返回字符串。
9、PromQL操作符
(1)数字运算符
就是简单的加减乘除。
通过prometheus_http_response_size_bytes_sum可以查询到Prometheus这个应用的 HTTP 响应字节总和。但是这个单位是字节,我们希望用 MB 显示:
prometheus_http_response_size_bytes_sum/8/1024
PromQL支持的所有数学运算符如下所示:
- + 加法
- - 减法
- * 乘法
- / 除法
- % 求余
- ^ 幂运算
(2)布尔运算符
布尔运算符支持用户根据时间序列中样本的值,对时间序列进行过滤。
我们可以通过prometheus_http_requests_total查询出每个接口的请求次数,筛选出请求次数超过20次的接口:
prometheus_http_requests_total > 20
上图的查询结果中,value还是具体的数值。如果想让符合条件的数据value变成1,不符合条件的数据value变成0。就要使用到修饰符 bool 。
prometheus_http_requests_total > bool 20
目前,Prometheus支持以下布尔运算符如下:
- * == 相等
- != 不相等
- > 大于
- < 小于
- >= 大于等于
- <= 小于等于
(3)集合运算符
通过集合运算符,可以对两个瞬时向量之间进行操作。目前,Prometheus支持以下集合运算符:
- and 与操作
- or 或操作
- unless 排除操作
unless 排除操作:
vector1 和 vector2先进行或操作,产生了一个新的集合。在该集合中,首先取vector1中的所有元素,然后排出所有在vector2中存在的元素。
假如vector1有A、B、C,vector2有B、C、D,则vector1 unless vector2 的结果为:A
在PromQL操作符中优先级由高到低依次为:
- ^
- *, /, %
- +, -
- ==, !=, <=, <, >=, >
- and, unless
- or
10、PromQL聚合操作
Prometheus提供了聚合操作符,可以将瞬时表达式返回的样本数据进行聚合,形成一个新的时间序列。目前支持的聚合函数:
- sum 求和
- min 最小值
- max 最大值
- avg 平均值
- stddev 标准差
- stdvar 标准方差
- count 计数
- count_values 对value进行计数
- bottomk 后n条时序
- topk 前n条时序
- quantile 分位数
(1)sum求和
用于对记录的 value 值进行求和
统计所有 HTTP 请求的次数
sum(prometheus_http_requests_total)
(2)min 最小值
返回所有记录的最小值。
筛选出最小的记录值
min(prometheus_http_requests_total)
(3)max 最大值
返回所有记录的最大值。
筛选出最大的记录值
max(prometheus_http_requests_total)
(4)avg 平均值
返回所有记录的平均值。
计算所有数据的value的平均值
avg(prometheus_http_requests_total)
(5)stddev 标准差
标准差(Standard Deviation)常用来描述数据的波动大小。即为了表示一组数据偏离平均值的程度。
加入现在有两个篮球队,统计两队篮球队员的身高。
两个队伍的平均身高都是180,但是画图的话如下:
而这两个队伍可以通过公式计算窗户标准差。
可以看出,橙色队伍的标准差比蓝色队伍标准差大得多,说明橙色队伍的身高波动更大。
stddev(prometheus_http_requests_total)
(6)count 计数
返回所有记录的条数合。
count(prometheus_http_requests_total)
(7)boottomk 后几条
用于对样本值进行排序,返回当前样本值后N位的时间序列。
获取HTTP请求量后5位的请求
bottomk(5, prometheus_http_requests_total)
(8)topk 前几条
用于对样本值进行排序,返回当前样本前N为的时间序列。
获取HTTP请求量前5位的请求
topk(5, prometheus_http_requests_total)
11、PromQL内置函数
PromQL 提供了大量的内置函数,可以对时序数据进行丰富的处理。
(1)rate增长率
有的样本值是不断变换的,counter类型指标的特点是只增不减,因此为了能直观的观察到长期变化情况,需要计算样本的增长率。
increase(v range-vector)函数是PromQL内置函数之一。其中参数v表示一个区间向量。increase函数获取区间向量中的第一个和最后一个样本并返回其增长量。
可以通过以下表达式Counter类型指标的增长率:
increase(node_cpu[2m]) / 120
这里通过node_cpu[2m]获取时间序列最近两分钟的所有样本,increase计算出最近两分钟的增长量,最后除以时间120秒得到node_cpu样本在最近两分钟的平均增长率。
rate(v range-vector)函数也是PromQL内置函数之一,可以直接计算区间向量v在时间窗口内平均增长速率。
通过以下表达式可以得到与increase函数相同的结果
rate(node_cpu[2m])
irate(v range-vector)函数同样用于计算区间向量的增长率,但是其反应的是瞬时增长率。因为使用rate或者increase函数去计算样本的增长率,容易陷入【长尾问题】,其无法反应在时间窗口内样本数据的复发变化。 例如,对于主机而言在 2 分钟的时间窗口内,可能在某一个由于访问量或者其它问题导致 CPU 占用 100% 的情况,但是通过计算在时间窗口内的平均增长率却无法反应出该问题。
irate 函数是通过区间向量中最后两个样本数据来计算区间向量的增长速率。
通过 irate 函数绘制的图标能够更好的反应样本数据的瞬时变化状态
irate(node_cpu[2m])
(2)predict_linear 增长预测
通常情况下,系统管理员为了确保业务的持续可运行,会针对服务器的资源设置相应的告警阈值。例如,当磁盘空间只剩512MB时向相关人员发送告警通知。但是当资源不是平滑变化时,比如有些某些业务增长,存储空间的增长速率提升了高几倍。这时,如果基于原有阈值去触发告警,当系统管理员接收到告警以后可能还没来得及去处理问题,系统就已经不可用了。
predict_linear(v range-vector,t scalar) 函数可以预测时间序列 v 在 t 秒之后的值。
基于2小时的样本数据,来预测主机可用磁盘空间的是否在4个小时候被占满,可以使用如下表达式:
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0