Grafana是现在最流行的开源数据可视化工具广泛用于监控分析仪表盘等场景。

很多人都用过Grafana配置数据源创建仪表盘添加面板设置告警等等,但是大部分人只会基本的使用对于Grafana的底层原理和机制可能不太了解。

我最近深入研究了Grafana的源码和架构对它的底层机制有了更深入的理解。

今天想深入剖析Grafana的可视化原理和底层机制包括整体架构数据源查询面板渲染告警等等帮大家更深入地理解Grafana。

一、Grafana简介

在讲原理之前,先简单介绍一下Grafana。

Grafana是一个开源的数据可视化平台由Torkel Ödegaard在,2013年创建后来成立了Grafana Labs公司持续开发和维护。

Grafana的核心功能是把各种数据源的数据可视化成图表仪表盘支持多种数据源,比如GraphiteInfluxDBPrometheusElasticsearchMySQLPostgreSQL等等几乎支持所有主流的时序数据库和关系型数据库。

Grafana的特点:

  1. 丰富的可视化:支持多种图表类型折线图柱状图饼图表格热力图仪表盘等等能满足各种可视化需求。
  2. 灵活的仪表盘:能自由拖拽布局面板支持变量模板重复面板等等能创建复杂的仪表盘。
  3. 强大的告警:支持多种告警规则和通知方式邮件钉钉企业微信Slack等等能及时发现和通知问题。
  4. 多租户:支持组织团队用户权限管理能多租户使用适合企业场景。
  5. 插件生态:支持插件扩展数据源面板应用等等有丰富的插件生态。
  6. 开源免费:核心功能开源免费社区版就能满足大部分需求也有企业版提供更多高级功能。

Grafana现在已经成为监控可视化领域的事实标准几乎所有做监控的团队都在用Grafana。

二、整体架构

Grafana的整体架构是前后端分离的前端用Angular(老版本)或React(新版本)开发后端用Go开发数据存储用SQLiteMySQL或PostgreSQL。

前端架构

Grafana的前端负责UI渲染和用户交互主要组件:

  1. Dashboard(仪表盘):仪表盘是Grafana的核心概念一个仪表盘包含多个面板和变量布局配置等等。
  2. Panel(面板):面板是仪表盘的基本单元每个面板有,自己的数据源查询可视化类型配置等等。
  3. Row(行):行用来分组面板能折叠展开方便管理大量面板。
  4. Variable(变量):变量用来参数化仪表盘能动态切换数据源主机服务等等实现仪表盘的复用。
  5. Datasource(数据源):数据源配置连接各种数据库的信息前端通过数据源查询数据。
  6. Query Editor(查询编辑器):每种数据源有,自己的查询编辑器用来编辑查询语句或条件。
  7. Renderer(渲染器):每种面板类型有自己的渲染器把查询到的数据渲染成图表。

后端架构

Grafana的后端负责API数据查询告警用户权限等等主要组件:

  1. HTTP API:提供RESTful API前端通过API和,后端交互包括仪表盘CRUD数据源CRUD用户管理等等。
  2. Datasource Proxy(数据源代理):前端查询数据的时候,不是直接连数据库而是通过后端的数据源代理转发请求这样能统一管理数据源凭证也能做缓存和权限控制。
  3. Alert Engine(告警引擎):负责评估告警规则触发告警发送通知是后端的重要组件。
  4. Auth(认证授权):负责用户认证和授权支持多种登录方式本地账号LDAPOAuth等等也支持细粒度的权限控制。
  5. Store(存储):负责数据持久化存储仪表盘数据源用户组织等等配置数据支持SQLiteMySQLPostgreSQL。
  6. Plugin Manager(插件管理器):负责加载和,管理插件包括数据源插件面板插件应用插件等等。
  7. Render Service(渲染服务):负责仪表盘的图片渲染用于告警通知里的图片和,PDF导出用Headless Chrome渲染。

数据流

Grafana的数据流大概是这样的:

  1. 用户在前端打开仪表盘前端根据仪表盘配置和变量生成查询请求。
  2. 前端把查询请求发给后端的数据源代理API。
  3. 后端根据数据源类型和配置连接对应的数据库执行查询。
  4. 数据库返回查询结果后端把结果转换成统一的格式返回给前端。
  5. 前端拿到数据传给面板的渲染器渲染成图表。
  6. 用户看到可视化的图表。

这个流程里后端的数据源代理是关键它屏蔽了不同数据源的差异给前端提供统一的接口也能做缓存和,权限控制。

三、数据源机制

Grafana支持多种数据源每种数据源有自己的插件实现查询和数据转换。

数据源插件结构

一个数据源插件主要包含两部分:

  1. 前端部分:查询编辑器和数据转换逻辑用TypeScript/JavaScript开发运行在浏览器里。
  2. 后端部分:(可选)如果需要后端处理,比如认证加密缓存等等会有后端插件用Go开发运行在Grafana后端里。

大部分数据源插件,只有前端部分查询请求通过后端的代理转发到数据库前端拿到原始数据后自己转换成Grafana的统一数据格式。

一些复杂的数据源,比如MySQLPostgreSQL等等有后端部分后端负责执行SQL查询转换数据格式返回给前端。

统一数据格式

Grafana定义了统一的数据格式,不管什么数据源查询到的数据都要转换成这种格式才能被面板渲染器使用。

主要有两种数据格式:

  1. Time Series(时序数据):用于时序图表,比如折线图柱状图等等格式是数组每个元素是一个时序包含target(名称)和datapoints(数据点数组每个数据点是[value, timestamp])。
[
  {
    "target": "cpu_usage",
    "datapoints": [
      [10.5, 1538745600000],
      [12.3, 1538745660000],
      [11.8, 1538745720000]
    ]
  },
  {
    "target": "memory_usage",
    "datapoints": [
      [45.2, 1538745600000],
      [46.1, 1538745660000],
      [45.8, 1538745720000]
    ]
  }
]
  1. Table(表格数据):用于表格面板格式是对象包含columns(列定义)和,rows(行数据)。
{
  "columns": [
    {"text": "Time", "type": "time"},
    {"text": "Host", "type": "string"},
    {"text": "CPU", "type": "number"}
  ],
  "rows": [
    [1538745600000, "host1", 10.5],
    [1538745600000, "host2", 12.3],
    [1538745660000, "host1", 11.8]
  ]
}

数据源插件的核心工作就是把数据库返回的原始数据转换成这两种格式之一,然后面板渲染器就能统一处理了。

数据源代理

Grafana的后端有一个数据源代理前端查询数据的时候,请求发到/api/datasources/proxy/:id/*后端根据数据源ID找到数据源配置,然后转发请求到对应的数据库。

数据源代理的作用:

  1. 统一管理凭证:数据库的用户名密码API Key等等凭证存在,后端的数据源配置里前端不需要知道也不会暴露给浏览器更安全。
  2. 跨域代理:浏览器有跨域限制前端不能直接请求不同域的数据库通过后端代理能解决跨域问题。
  3. 缓存:后端能对查询结果做缓存减少数据库的压力提高查询速度。
  4. 权限控制:后端能根据用户权限控制能查询哪些数据做数据隔离。
  5. 日志和监控:后端能记录查询日志监控查询性能方便排查问题。

四、查询机制

Grafana的查询机制很灵活支持多种查询方式和变量替换。

查询编辑器

每种数据源有自己的查询编辑器用户在面板编辑界面里用查询编辑器编写查询。

比如Prometheus的查询编辑器是输入PromQL语句InfluxDB的查询编辑器是图形化的选择measurementfieldtag等等MySQL的查询编辑器是输入SQL语句。

查询编辑器会把用户输入的查询保存在面板的配置里打开仪表盘的时候,前端读取面板配置拿到查询,然后发给后端查询。

变量替换

Grafana支持变量能在查询里引用变量查询的时候,变量会被替换成当前选中的值。

比如定义了一个变量$host选项是host1host2host3查询里写cpuusage{host="$host"}当用户选host1的时候,查询会被替换成cpuusage{host="host1"}查询host1的CPU数据。

变量支持多种类型:

  1. Query(查询变量):通过查询数据源动态获取变量选项,比如查询所有主机名。
  2. Custom(自定义变量):手动输入变量选项逗号分隔。
  3. Interval(间隔变量):时间间隔变量,比如1m5m1h用来控制查询的聚合间隔。
  4. Datasource(数据源变量):切换数据源的变量。
  5. Constant(常量变量):常量隐藏的变量用来存固定值。
  6. Ad hoc filters(临时过滤器):临时添加的过滤器能动态添加查询条件。

变量还支持多选全选级联等等功能非常灵活能实现复杂的仪表盘参数化。

查询转换

Grafana的面板支持查询转换能对查询到的数据做进一步处理,比如过滤排序计算合并等等。

主要的转换操作:

  1. Filter by name(按名称过滤):过滤掉不需要的时序。
  2. Sort by name(按名称排序):按时序名称排序。
  3. Add field from calculation(计算添加字段):基于现有字段计算新字段。
  4. Merge(合并):合并多个查询的结果。
  5. Series to rows(时序转行):把时序数据转换成表格行。
  6. Rows to series(行转时序):把表格行转换成时序数据。
  7. Organize fields(组织字段):重命名隐藏重排字段。

这些转换操作能让用户不用改查询就能对数据做处理很方便特别是对于不会写复杂查询的用户。

五、面板渲染机制

Grafana的面板渲染是前端的核心负责把数据可视化成图表。

面板插件结构

一个面板插件主要包含:

  1. Module(模块):面板的主类定义面板的行为和生命周期。
  2. Editor(编辑器):面板的配置编辑器用户配置面板的界面。
  3. Renderer(渲染器):面板的渲染逻辑把数据渲染成图表。
  4. HTML模板:面板的HTML模板定义面板的结构。
  5. CSS:面板的样式。

Grafana的面板渲染大部分用SVG或Canvas实现老版本主要用Flot(jQuery图表库)新版本逐步迁移到uPlot(高性能Canvas图表库)性能更好。

渲染流程

面板的渲染流程大概是:

  1. 仪表盘打开或刷新的时候,前端遍历所有面板发起数据查询。
  2. 数据查询完成后前端把数据传给对应面板的渲染器。
  3. 渲染器根据面板配置和数据计算图表的布局坐标颜色等等。
  4. 渲染器用SVG或Canvas绘制图表到面板的DOM元素里。
  5. 用户和图表交互的时候,比如鼠标悬停缩放拖拽渲染器更新图表显示tooltip等等。

时间范围控制

Grafana的仪表盘有全局的时间范围控制用户能选择查看最近1小时6小时24小时7天等等的数据也能自定义时间范围。

时间范围会传给所有面板的查询查询对应时间范围的数据渲染图表的时候X轴也会用这个时间范围。

Grafana还支持时间缩放用户能在图表上拖拽选择时间范围放大查看细节也能点击图表的时间轴缩放时间范围。

自动刷新

Grafana支持自动刷新用户能设置刷新间隔,比如5秒1分钟5分钟等等到时间自动刷新所有面板的数据更新图表。

自动刷新对于实时监控很重要能及时看到最新的数据发现问题。

六、告警机制

Grafana的告警是后端的重要功能能根据面板的查询数据评估告警规则触发告警发送通知。

告警规则

每个面板能配置告警规则定义在什么条件下触发告警。

告警规则主要包含:

  1. 名称:告警规则的名称。
  2. 查询条件:基于面板的查询定义评估的查询和时间范围。
  3. 条件:触发告警的条件,比如平均值大于阈值持续多久等等。
  4. 无数据处理:查询无数据的时候,怎么处理告警保持当前状态触发告警还是忽略。
  5. 错误处理:查询出错的时候,怎么处理。
  6. 通知:告警触发的时候,发送通知给哪些通知渠道和用户。

告警评估

Grafana的后端有一个告警引擎定期评估所有告警规则。

评估流程:

  1. 告警引擎定时(默认10秒)遍历所有启用的告警规则。
  2. 对每个告警规则执行查询获取数据。
  3. 根据告警条件评估数据判断是否触发告警。
  4. 如果条件满足且持续时间达到设置触发告警更新告警状态为alerting。
  5. 如果条件不满足告警状态恢复为ok。
  6. 告警状态变化的时候,发送通知。

告警状态有几种:

  1. ok:正常没有触发告警。
  2. pending:条件满足,但是还没达到持续时间等待中。
  3. alerting:告警触发中。
  4. no_data:查询无数据。
  5. paused:告警被暂停。
  6. execution_error:查询执行出错。

通知渠道

Grafana支持多种通知渠道告警触发的时候,能发送通知到:

  1. 邮件:发送告警邮件包含告警信息和面板截图。
  2. 钉钉:发送告警到钉钉群机器人。
  3. 企业微信:发送告警到企业微信群机器人。
  4. Slack:发送告警到Slack频道。
  5. Webhook:发送告警到自定义的WebhookURL能对接自定义系统。
  6. PagerDuty:发送告警到PagerDuty值班系统。
  7. OpsGenie:发送告警到OpsGenie。
  8. VictorOps:发送告警到VictorOps。
  9. Kafka:发送告警到Kafka消息队列。
  10. Line:发送告警到Line。

通知渠道能在告警配置里选择多个,同时发送到多个渠道确保告警能及时送达。

告警图片渲染

告警通知里能包含面板的截图让接收者直观看到告警时的图表情况。

Grafana用Headless Chrome(无头浏览器)渲染仪表盘的面板截图保存为图片,然后附在告警通知里。

这个渲染服务是后端的一个组件需要安装Chrome或Chromium才能使用,如果没安装告警通知就没有图片,只有文字。

七、权限和多租户

Grafana支持多租户和细粒度的权限控制适合企业场景。

组织(Organization)

Grafana的最高租户单位是组织每个组织有自己的数据源仪表盘用户等等数据隔离不同组织的用户看不到对方的数据。

一个用户能属于多个组织切换组织的时候,看到的数据也会切换。

团队(Team)

组织下能创建团队团队是用户的分组能给团队授权权限团队里的用户继承团队的权限。

用户角色

Grafana有几种用户角色:

  1. Admin(管理员):组织管理员能管理组织的所有设置用户数据源仪表盘等等。
  2. Editor(编辑者):能创建编辑仪表盘和数据源,但是不能管理用户和组织设置。
  3. Viewer(查看者):只能查看仪表盘不能编辑。
  4. Grafana Admin(超级管理员):整个Grafana的管理员能管理所有组织和用户,只有一个默认admin用户。

仪表盘权限

除了全局的角色权限Grafana还支持仪表盘级别的权限能给特定的用户或团队授权特定仪表盘的查看或编辑权限更细粒度控制。

比如能设置某个仪表盘,只有某个团队能查看其他用户看不到适合敏感数据的场景。

数据源权限

Grafana企业版还支持数据源级别的权限能控制哪些用户能查询哪些数据源做数据隔离社区版没有这个功能。

八、插件机制

Grafana的插件机制很灵活能扩展Grafana的功能。

插件类型

Grafana的插件主要有三种:

  1. 数据源插件(Datasource Plugin):扩展支持的数据源,比如新的数据库API等等。
  2. 面板插件(Panel Plugin):扩展支持的面板类型,比如新的图表可视化方式。
  3. 应用插件(App Plugin):扩展Grafana的应用功能,比如完整的监控解决方案包含数据源面板仪表盘等等。

插件安装

Grafana的插件能通过几种方式安装:

  1. grafana-cli:命令行工具grafana-cli plugins install <plugin-id>能从Grafana插件市场下载安装插件。
  2. 手动安装:下载插件压缩包解压到Grafana的plugins目录重启Grafana。
  3. 环境变量:通过环境变量GFINSTALLPLUGINS启动时自动安装插件适合Docker部署。

插件开发

Grafana提供了插件开发工具和文档能开发自己的插件。

插件开发主要用TypeScript和React(新版本)或Angular(老版本)后端插件用Go开发。

Grafana提供了插件脚手架工具grafana-toolkit plugin:create能快速创建插件项目模板包含基本的代码结构和构建配置。

开发好的插件能提交到Grafana插件市场供其他人使用也能私有部署在自己的Grafana里。

九、性能优化

Grafana在大规模使用的时候,可能会有性能问题需要做一些优化。

常见性能瓶颈

  1. 查询慢:数据源查询慢导致面板加载慢可能是数据库性能问题,或者查询写得不好数据量大。
  2. 渲染慢:面板渲染慢特别是数据点多的时候SVG渲染性能不够。
  3. 告警评估慢:告警规则多的时候,告警评估慢占用大量资源。
  4. 数据库慢:Grafana自己的元数据数据库慢,比如仪表盘多用户多SQLite性能不够。
  5. 并发高:用户多并发查询高Grafana后端压力大。

优化方法

  1. 优化查询:优化数据源的查询减少查询的数据量和,时间范围用聚合降采样等等减少返回的数据点。
  2. 使用缓存:对查询结果做缓存特别是变化不频繁的数据减少数据库压力Grafana企业版有查询缓存功能社区版能用数据源侧的缓存,比如Redis。
  3. 升级渲染引擎:用新版本的Grafana渲染引擎从Flot迁移到uPlot性能提升很多特别是大数据量的情况。
  4. 优化告警:减少不必要的告警规则调整告警评估间隔用告警分片(企业版)分布式评估告警。
  5. 用MySQL/PostgreSQL替代SQLite:大规模使用的时候,不要用SQLite换成MySQL或PostgreSQL性能更好支持更多并发。
  6. 横向扩展:Grafana后端能横向扩展部署多个实例前面加负载均衡提高并发能力,但是要注意会话共享和告警评估去重。
  7. 硬件升级:升级CPU内存磁盘用SSD提高IO性能特别是数据库和,渲染服务。

十、写在最后

以上就是Grafana可视化原理的深入剖析理解了Grafana的底层机制。

Grafana是一个非常优秀的开源数据可视化工具架构清晰功能强大插件生态丰富能满足各种监控可视化需求。

理解了Grafana的底层原理能帮我们更好地使用Grafana遇到问题能更快地排查和,解决也能根据需求做定制和扩展。

当然Grafana的功能很多本文只是讲了核心的原理和机制,还有很多细节需要在实际使用中慢慢体会和学习。

建议大家有时间的话,看看Grafana的源码和官方文档深入理解它的设计和实现会有很多收获。

如果有什么问题,或者不同的看法欢迎在评论区留言我们一起交流。

最后用一句话结束这篇文章:"Grafana是监控可视化的利器理解原理才能用得更好。"

愿大家都能用好Grafana搭建出优秀的监控仪表盘及时发现和解决问题。