深入浅出开源监控系统Prometheus(上)
本文首发于 vivo互联网技术 微信公众号
链接: https://mp.weixin.qq.com/s/4NC4spF6cEvXuIBKVbIU7A
作者:ZhangShuo
Prometheus是继Kubernetes(k8s)之后,CNCF毕业的第二个开源项目,其来源于Google的Borgmon。本文从“监控”这件事说起,深入浅出Prometheus的架构原理、目标发现、指标模型、聚合查询等设计核心点。
一、前言
接触过各式各样的监控,开源的CAT、Zipkin、Pinpoint等等,并深度二次开发过;也接触过收费的听云系APM,对各类监控的亮点与局限有足够的了解。
去年10月我们快速落地了一套易用、灵活、有亮点的业务监控平台,其中使用到了Prometheus。从技术选型阶段,Prometheus以及它的生态就让我们印象深刻,今天就聊聊监控设计与Prometheus。
通常一个监控系统主要包含 采集(信息源:log、metrics)、上报(协议:http、tcp)、聚合、存储、可视化以及告警等等。其中采集上报主要是客户端的核心功能,一般有定期外围探测的(早期的Nagios、Zabbix)、AOP方式手动织入代码的(埋点)、字节码自动织入等方式(无埋点)。
二、什么是监控
一套产品化的,用来量化管理技术、业务的服务体系或解决方案。
这套产品主要解决两个问题(产品价值):
- 技术:将系统的各种功能、状态等技术表现数据化、可视化,来保证技术体系的稳定、安全等。
- 业务:将各种业务表现数据化、可视化,以供分析、及时干预,保证业务高效开展。
三、监控的基础原则
- 事前监控:架构设计阶段务必需要考虑监控,而不是等到部署上线才去考虑
- 监控什么:全局视角,自顶(业务)向下。对于一般业务来讲,建议先监控离用户最近的地方,用户的良好体验是推动业务发展的动力,这也是最敏感、重要的地方。
- 对用户友好:监控服务易用,易接入,尽可能自动化
- 技术人员、业务人员的信息源、能够协助故障定位与解决
- 可视化:清晰的显示各类数据(各类图表展示),以及告警等信息记录
-
告警:
哪些问题需要通知?(如:需要人工干预的,有意义的)
通知谁?(如:一线系统负责人)
如何通知?(如:短信、电话、其他通信工具;信息清晰、准确、可操作)
多久通知一次?(如:5分钟)
何时停止通知以及何时升级到其他人?(如:已恢复正常;两个小时问题未恢复,升级通知到上级负责人)
四、Prometheus设计剖析
Prometheu聚焦于当下正在发生的各类数据,而不是追踪数周以前的数据,因为他们认为“大多数监控查询以及告警等都是一天内的数据”,Facebook相关论文也验证了这一点:85%的时序查询是26小时之内的。
简单来概括,Prometheus是一个准实时监控系统,并自带时序数据能力。
1. 整体架构
Prometheus架构图(引用自Prometheus官网)
简化点的架构图如下:
Prometheus 主要通过pull的方式获取被监控程序(target\exports)中暴漏出来的时序数据。当然也提供了pushgateway服务,一般少量数据也可以push方式发送。
2. 目标发现
Prometheus通过pull的方式获取服务的指标数据,那么它是如何发现这些服务的呢?
可以通过多种方式来处理目标资源的发现:
2.1 人工的配置文件列表
通过手工方式,添加静态配置,指定需要监控的服务,如下target块:
prometheus.yml
scrape_configs: ..... #监控活动 - job_name: 'xxxxxxactivity-wap' metrics_path: /prometheus/metrics static_configs: - targets: ['10.xx.xx.xx:8080', ...... ......] #监控优惠券 - job_name: 'xxxxxxshop-coupon' metrics_path: /prometheus/metrics static_configs: - targets: ['10.xx.xx.xx:8080', ...... ......] #营销 - job_name: 'xxxxxx-sales-api' metrics_path: /prometheus/metrics static_configs: - targets: ['10.xx.xx.xx:8080', ...... ...... ] ......
显而易见,这种方式虽然很简单,但是在繁忙的工作中持续维护一长串服务主机列表并不是一个可扩展的优雅方式,动态性、大规模会让这种方式无法继续下去。
指定加载目录,这些目录文件的变更将通过磁盘监视检测发现,然后Prometheus会立即应用这些变更。作为备用方案,文件内容也将以指定的刷新间隔(refresh_interval)定期被Prometheus重新读取,发现变更后生效。
示例如下:
prometheus.yml
...... #监控 订单中心OMS-API scrape_configs: - job_name: 'oms-api' metrics_path: /prometheus/metrics file_sd_configs: - files: - 'conf/oms-targets.json' #默认 5分钟 refresh_interval:5m ......
conf/oms-targets.json文件(此文件的变动将被监听,通常这个文件由另一个程序产生,如CMDB源):
oms-targets.json
[ { "labels": { "job": "oms-api" }, "targets": [ 'ip1:8080','ip2:8080',...... ] } ]
2.3 基于API的自动发现
当前可以用的本机服务发现插件有AmazonEC2、Azure、Consul、Kubernetes等等。
下文以Consul为例,实例启动成功时可以通过脚本(或其他)方式将当前节点信息,注册到Consul上(类似启动后向zk或redis写入当前节点信息)。Prometheus会实时的感知到Consul数据的变动,并自动去做热加载。
prometheus.yml
#监控 订单中心OMS-API - job_name: 'oms-api' consul_sd_configs: #consul 地址,默认监听所有服务地址信息 - server: 'xxxxxx' services: []
注:Consul 是基于 GO 语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册、服务发现和配置管理的功能。Consul 提供服务注册/发现、健康检查、Key/Value存储、多数据中心和分布式一致性保证等功能
2.4 基于DNS的自动发现
在前几种方式都不适合的情况下,DNS服务发现允许你指定DNS条目列表,然后查询这些条目中的记录,以发现获取目标列表。用的比较少,不赘述。
被监控的目标成功被发现后,可以在自带的web页面上可视化查看,如图(本地模拟环境):
3. 指标收集与聚合
Prometheus通过pull的方式拉取外部进程中的时序数据指标(Exporter),拉取过程细节允许用户配置相关信息:如频率、提前聚合规则、目标进程暴漏方式(http url)、如何连接、连接身份验证等等。
指标
所谓指标就是软件或硬件多种属性的量化度量。有别于日志采集的那种ELK监控,Prometheus通过四种指标类型完成:
(1)测量型(Gauge):可增可减的数字(本质上是度量的快照)。常见的如内存使用率。
(2)计数型(counter):只增不减,除非重置为0。比如某系统的HTTP请求量。
(3)直方图(histogram):通过对监控的指标点进行抽样,展示数据分布频率情况的类型。
上图强调了分布情况对于理解延迟等指标的重要性。如果我们假设这个指标的SLO(服务等级目标)为150ms,那么137ms的平均延迟看起来是可以接受的;但实际上,每10个请求中就有1个在193ms以上完成,每100个请求中就有10个不达标!(如图:90线、99线均不达标)
(4)摘要(summary):与Histogram非常类似,主要区别是summary在客户端完成聚合,而Histogram在服务端完成。因此summary只适合不需要集中聚合的单体指标(如GC相关指标)。
三条经验法则:
- 如果需要多个采集节点的数据聚合、汇总,请选择直方图;
- 如果需要观察多个采集节点数据的分布情况,请选择直方图;
- 如果不需要考虑集群(如GC相关信息),可选择summary,它可以提供更加准确的分位数。
4. 聚合、查询
内置的数据查询DSL语言:PromQL,它可以快速的支持聚合和多种形式的查询,并通过自带的web界面,可以快速在浏览器中查询使用。在我们的实践中,使用Grafana做可视化更加实用、美观。
关于PromQL更多语法使用,可以查看官网文档,不赘述。
关于指标聚合
对于指标的聚合,Prometheus提供了多种函数。以下列聚合指标为例:
-
平均数
-
中间数
-
百分位数(如下图99线:百分之99的请求要低于12s这个值)
-
标准差(衡量数据集差异情况,0代表与平均数一样,越大表示数据差异越大)
-
变化率
5. 数据模型
Prometheus与其他主流时序数据库一样,在数据模型定义上,也会包含metric name、一个或多个labels(同InfluxDB里的tags含义)以及metric value。
如用JSON表示一个时序数据库中的原始时序数据:
一个json表示的时序数据示例
##用JSON表示一个时序数据 { "timestamp": 1346846400, // 时间戳 "metric": "total_website_visits", // 指标名 "tags":{ // 标签组 "instance": "aaa", "job": "job001" }, "value": 18 // 指标值 }
metric name加一组labels作为唯一标识来定义time series(也就是时间线)。一旦label改变,则会创建新的时间序列,原有基于这个时间序列的配置将无效。在查询时,支持根据labels条件查找time series,支持简单的条件也支持复杂的条件。
上图是所有数据点分布的一个简单视图,横轴是时间,纵轴是时间线,区域内每个点就是数据点。Prometheus每次接收数据,收到的是图中区域内纵向的一条线。这个表述很形象,因为在同一时刻,每条时间线只会产生一个数据点,但同时会有多条时间线产生数据,把这些数据点连在一起,就是一条竖线。这个特征很重要,影响数据写入和压缩的优化策略。
保留时间
Prometheus专注于短期监控、告警而设计,所以默认它只保存15天的时间序列数据。如果要更长期,建议考虑数据单独存储到其他平台。目前我们的方案是远端存储,Prometheus拉取的数据会落到InfluxDB上,这样保证了更好的存储弹性,数据的实时落地存储。
6.Prometheus开源生态
Prometheus生态系统包括了提供告警引擎、告警管理的AlertManager,支持push模式数据上报的PushGateWay,提供更优雅美观的可视化界面的Grafana,支持远端存储的RemoteStoreAdapter;log转换为metric的Mtail等等。
除此之外,还有一系列Exporter(可以理解为监控agent),这些Exporter可以直接安装使用。自动监控应用程序、机器、主流数据库、MQ等等。
Prometheus生态中还有一系列客户端库,支持各种主流编程语言Java、C、Python等等。
可以说Prometheus的生态是比较完善的,并且社区足够活跃,未来可期。
更多内容敬请关注 vivo 互联网技术 微信公众号
注:转载文章请先与微信号:Labs2020 联系
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
通俗易懂:说说 Python 里的线程安全、原子操作
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 在并发编程时,如果多个线程访问同一资源,我们需要保证访问的时候不会产生冲突,数据修改不会发生错误,这就是我们常说的 线程安全 。 那什么情况下,访问数据时是安全的?什么情况下,访问数据是不安全的?如何知道你的代码是否线程安全?要如何访问数据才能保证数据的安全? 本篇文章会一一回答你的问题。 1. 线程不安全是怎样的? 要搞清楚什么是线程安全,就要先了解线程不安全是什么样的。 比如下面这段代码,开启两个线程,对全局变量 number 各自增 10万次,每次自增 1。 正常我们的预期输出结果,一个线程自增100万,两个线程就自增 200 万嘛,输出肯定为 2000000 。 可事实却并不是你想的那样,不管你运行多少次,每次输出的结果都会不一样,而这些输出结果都有一个特点是,都小于 200 万。 以下是执行三次的结果 这种现象就是线程不安全,究其根因,其实是我们的操作 number += 1 ,不是原子操作,才会导致的线程不安全。 2. 什么是原子操作? 原子操作(atomic operati...
- 下一篇
领域驱动设计(DDD)实践之路(三):如何设计聚合
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/oAD25H0UKH4zujxFDRXu9Q 作者:wenbo zhang 【领域驱动设计实践之路】往期精彩文章: 《领域驱动设计(DDD)实践之路(一)》 主要讲述了战略层面的DDD原则 《领域驱动设计(DDD)实践之路(二):事件驱动与CQRS》分析了如何应用事件来分离软件核心复杂度。 这是“领域驱动设计实践之路”系列的第三篇文章,分析了如何设计聚合。聚合这个概念看似很简单,实际上有很多因素导致我们建立不正确的聚合模型。本文对这些问题逐一进行剖析。 聚合这个概念看似很简单,实际上有很多因素导致我们建立不正确的聚合模型。一方面,我们可能为了使用上的一时便利将聚合设计得很大。另一方面,因为边界、职责的模糊性将一些重要的方法放在了其他地方进而导致业务规则的泄露,没有达到聚合对业务边界的保护目的。在开始聚合之前,我们要区分清楚“实体Entity”“值对象Value Obj”的区别,并且要重视“值对象Value Obj”的真正价值。 (图片来源于网络) 一、实体(Entity) OR 值对...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS关闭SELinux安全模块
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2配置默认Tomcat设置,开启更多高级功能