Prometheus 源码解读(一)
Prometheus 源码解读(一)
Prometheus 是云原生监控领域的事实标准,越来越来的开源项目开始支持 Prometheus 监控数据格式。从本篇开始,我将和大家一起阅读分析 Prometheus 源码。学习 Prometheus 的设计理念,了解 Prometheus 的局限性与不足。本系列分八个板块逐一拆解 Prometheus 源码。本文基于 Prometheus v2.13.0。
- 工作原理与架构
- 时序数据库模块(TSDB)
- 配置文件加载模块(Configuration Reloader)
- 服务发现模块(Service Discovery Manager)
- 数据抓取模块(Scrape Manager)
- RES API 模块(Web Handler)
- 查询引擎(Query Engine & PromQL)
- 性能与优劣势总结
1. Prometheus 介绍
Prometheus 是基于时序数据库(Time Series Database, TSDB)的监控告警系统。Prometheus 在 2016 年加入 CNCF 基金会,成为继 Kubernetes 后第二个毕业项目,其火热程度可见一斑。相比于传统的监控方案,Prometheus 有以下几个优势:
- 高效的存储引擎
Prometheus 将监控指标以时序数列的格式存储在时序数据库 TSDB 中。相比于传统的关系型数据库,时序数据库便于对已有数据进行聚合;在高并发的情况下,读写性能也远高于关系型数据库。Prometheus 2.0 版本重构了底层时序存储引擎。目前,单个 Prometheus 服务器可以做到每秒存储百万条指标数据,同时占用磁盘空间也很小
- 强大的查询能力:PromQL
Prometheus 有独立的 PromQL 查询语言,另外还提供了很多内置的基于时间的处理函数,降低数据聚合的难度

- 面向服务的架构
Prometheus 采用拉模型收集时序数据,数据拉取行为是由服务端来决定的。服务端可以通过某种服务发现机制来自动发现监控对象。而对于推模型的监控系统,客户端需要负责在服务端上进行注册及监控数据推送,这在微服务架构里实现起来比较难的。当大量客户端向服务的主动推送数据时,服务端的压力较大

- 与 Kubernetes 天然集成
Kubernetes 本身的指标也是以 Prometheus 格式暴露出来的
- 逐步完善的生态
OpenMetrics:Prometheus 的数据格式逐渐成为一种标准。OpenMetrics 正在从 Prometheus 的数据格式中分离出来,逐渐成为监控数据格式的国际标准
Thanos:支持数据存储的可伸缩,弥补 Prometheus 数据持久化方面的不足Prometheus
Prometheus Operator:简化 Prometheus 配置管理
2. 架构分析
图的左边开始是监控数据源。任何应用服务想要接入 Prometheus,都需要提供 HTTP 接口(通常是 x.x.x.x/metrics 地址),并暴露 Prometheus 格式的监控数据。Prometheus Server 通过 HTTP 协议周期性抓取监控目标的监控数据。Prometheus 提供了 Client 库帮助开发人员在自己的应用中集成 Prometheus 指标。
而对于不适合直接在代码中集成 Client 库的场景,比如应用来自第三方、不是由自己维护,应用不支持 HTTP 协议,那就需要为这些场景单独编写 Exporter 程序。Exporter 作为代理,把监控数据暴露出来。比如 Mysql Exporter,Node Exporter。
Prometheus 将采集到的数据存储在本地时序数据库中,但缺少数据副本。这也是 Prometheus 自身在数据持久化方面做的不足的地方。但这些存储问题都有其他的解决方案,Prometheus 支持 remote write 方式将数据存储到远端。
Prometheus 支持通过 Kubernetes、静态文本、Consul、DNS 等多种服务发现方式来获取抓取目标(targets)。最后,用户编写 PromQL 语句查询数据并进行可视化。

3. 核心组件
Prometheus 的功能由多个互相协作的组件共同完成。这些组件也即本文开头所列出的模块,比如 Service Discovery Manager。我们后续会逐一介绍。Prometheus 源码入口 main() 函数 完成参数初始化工作,并依次启动各依赖组件。
首先,main 函数解析命令行参数(详见附录 A),并读取配置文件信息(由 --config.file 参数提供)。Prometheus 特别区分了命令行参数配置(flag-based configuration)和文件配置(file-based configuration)。前者用于简单的设置,并且不支持热更新,修改需要启停 Prometheus Server 一次;后者支持热更新。
main 函数完成初始化、启动所有的组件。这些组件包括:Termination Handler、Service Discovery Manager、Web Handler 等。各组件是独立的 Go Routine 在运行,之间又通过各种方式相互协调,包括使用 Channel、引用对象 Reference、传递 Context。
这些 Go Routine 的协作使用了 oklog/run 框架。oklog/run 是一套基于 Actor 设计模式的 Go Routine 编排框架,实现了多个 Go Routine 作为统一整体运行并有序依次退出。这在很多开源项目中都有使用,进一步了解可参考作者的另一篇文章《Go routine 编排框架:oklog/run 包》

4. 参考文档
「K8S 技术落地实践」Prometheus 在 K8S 上的监控实践 来自本文作者在杭州容器 Meetup 的分享
Prometheus Internal architecture
附录 A:Prometheus 启动参数
- web:Prometheus 服务器 HTTP 连接参数,REST API 启用相关参数,Prometheus Console 网页配置
- storage:TSDB 相关配置
- query:查询执行相关配置
| 参数名 | 解释 |
|---|---|
| config.file | 配置文件的位置,包含抓取监控对象列表(用于服务发现)和 recording rules 文件位置 |
| web.listen-address | Prometheus server 端监听请求(API 请求、Dashboard 界面)的地址和端口,默认本地端口 9090 |
| web.read-timeout | 设置 Prometheus server 读取客户端请求的超时时间。以此来避免客户端因超慢的写操作,长时间占用链接资源。ReadTimeout 覆盖了从连接请求被接受到请求报文被完全读取的时间。默认 5m |
| web.max-connections | 最大连接数,默认 512 |
| web.external-url | 设置 Prometheus 对外的 URL。需要设置外部访问的 Prometheus 通常因为启用了反向代理。如果 external-url 包含路径,则 Prometheus 所有对外的接口,都会带上该路径作为前缀。eg. http://<host>:<port>/<path>/api/v1/query?query=up |
| web.route-prefix | 用于替换 external-url 的路径前缀,eg. http://<host>:<port>/<route-prefix>/api/v1/query?query=up |
| web.user-assets | 网页静态 asset 文件夹路径 |
| web.enable-lifecycle | 开启后,可以实现通过请求 /-/reload 热加载更新配置,默认 false |
| web.enable-admin-api | 开启后,允许使用一些管理员级别的 api,包括删除时间序列等,/api/v1/admin/tsdb/delete_series。默认 false |
| web.console.templates | Prometheus Console 网站模板文件夹路径 |
| web.console.libraries | Prometheus Console 使用的库路径 |
| web.page-title | Console 页面标题 |
| web.cors.origin | 设置 Prometheus 服务端允许的域,用正则表达式表示。eg. https?://(domain*)\.com |
| storage.tsdb.path | 监控数据存储路径,默认 data/ |
| storage.tsdb.min-block-duration | 设置数据块最小时间跨度,默认 2h 的数据量。监控数据是按块(block)存储,每一个块中包含该时间窗口内的所有样本数据(data chunks) |
| storage.tsdb.max-block-duration | 设置数据块最大时间跨度,默认为最大保留时间的 10% |
| storage.tsdb.wal-segment-size | 设置 WAL 分段存储每个分段的大小。默认 128MB |
| storage.tsdb.retention.time | 监控数据最大保留时间,默认 15d |
| storage.tsdb.no-lockfile | 不在数据存储目录中创建文件锁 |
| storage.tsdb.wal-compression | 开启后,会对 WAL 文件进行压缩(成本是带来 CPU 开销)。默认 false |
| storage.remote.flush-deadline | |
| storage.remote.read-sample-limit | 一次最多从远端存储中读取采样数据量,默认 5e7 条,0 表示无限制 |
| storage.remote.read-concurrent-limit | 最大并发读,默认 10 个请求,0 表示无限制 |
| rules.alert.for-outage-tolerance | |
| rules.alert.for-grace-period | |
| rules.alert.resend-delay | |
| alertmanager.notification-queue-capacity | |
| alertmanager.timeout | |
| query.lookback-delta | 在计算 PromQL 表达式结果时,最大回看时间 |
| query.timeout | 查询超时时间 |
| query.max-concurrency | 最大并发处理查询请求数,默认 20 个请求 |
| query.max-samples | 能载入到内存中最大采样数据量,默认 5e7 条 |
Prometheus 源码解读(一)的更多相关文章
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
- AFNetworking 3.0 源码解读 总结(干货)(下)
承接上一篇AFNetworking 3.0 源码解读 总结(干货)(上) 21.网络服务类型NSURLRequestNetworkServiceType 示例代码: typedef NS_ENUM(N ...
- AFNetworking 3.0 源码解读 总结(干货)(上)
养成记笔记的习惯,对于一个软件工程师来说,我觉得很重要.记得在知乎上看到过一个问题,说是人类最大的缺点是什么?我个人觉得记忆算是一个缺点.它就像时间一样,会自己消散. 前言 终于写完了 AFNetwo ...
随机推荐
- 喜大普奔,两个开源的 Spring Boot + Vue 前后端分离项目可以在线体验了
折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...
- 白话系列之IOC,三个类实现简单的Ioc
前言:博客园上已经有很多IOC的博客.而且很多写的很好,达到开源的水平,但是对于很多新人来说,只了解ioc的概念,以及怎么去使用ioc.然后想更进一步去看源码,但是大部分源码都比较困难,当不知道一个框 ...
- Linux 笔记 - 前三章 CentOS 简介、安装和远程连接
博客地址:http://www.moonxy.com 一.Unix 和 Linux 的区别 目前主流的 Unix 系统有三种,分别是 IBM-AIX.HP-UX.SUN-Solaris,它们分别运行在 ...
- 单线程Redis性能为何如此之高?
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 实际项目开发中现在无法逃避的一个问题就是缓存问题,而缓存问题也是面试必问知识点之一,如果面试官好一点可能会简单 ...
- MySQL命令窗口出现中文乱码的解决方法
查询表语句的时候,出现了中文乱码,但是用Navicat for MySQL查看的时候却是正常的,字符集都是设置的utf-8,如下图所示: 其实上大学学习java的时候也遇到了中文乱码但是却没有 ...
- Hadoop源代码点滴-系统结构(HDFS+YARN)
Hadoop建立起HDFS和YARN两个字系统,前者是文件系统,管数据存储:后者是计算框架,管数据处理. 如果只有HDFS而没有YARN,那么Hadoop集群可以被用作容错哦的文件服务器,别的就没有什 ...
- redis分布式锁-基本概念与实现方式对比
1.redis中使用WATCH实现锁机制,是最次之的方式.WATCH只会在数据被其他客户端抢先修改了的情况下,“通知”执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改.此类锁成为“乐观锁” ...
- Idea 设置Eclipse快捷键(常用)
使用Idea不习惯,特此将其配置成Eclipse风格的. 1.选择Eclipse风格,选择copy一份,可以自己重命名. 2.设置生成快捷键的快捷键(例如:Eclipse中的Alt+/) 3.设置ma ...
- Django之使用celery和NGINX生成静态页面实现性能优化
性能优化原理: 当我们要给client浏览器返回一个页面时,我们需要去数据库查询数据并将数据和基本页面模板渲染形成页面返回给客户端,但如果每一个用户访问时都去查询一次首页的的数据时,当日访问量很大时那 ...
- 使用scm-manager搭建git/svn 代码管理仓库
使用 scm-manager 搭建 git/svn 代码管理仓库 1.在官网上下载scm-manager 下载地址https://www.scm-manager.org/download/ 2. 配置 ...