ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

07 Telegraf插件设计

Telegraf 是 InfluxData 公司开源的一款十分流行的指标采集软件,在 GiHub 已有上万 Star。其借助社区的力量,拥有了多达 200 余种采集插件以及 40 余种导出插件,几乎覆盖了所有的监控项,例如机器监控、服务监控甚至是硬件监控。

架构设计

Pipeline 并发编程

在 Go 中,Pipeline 并发编程模式是一种常用的并发编程模式。简单来说,其整体上是由一系列阶段(stage),每个 stage 由一组运行着相同函数的 goroutine 组成,且各个 stage 之间由 channel 相互连接。

在每个阶段中,goroutine 负责以下事宜:

  1. 通过入口 channel,接收上游 stage 产生的数据。
  2. 处理数据,例如格式转换、数据过滤聚合等。
  3. 通过出口 channel,发送处理后的数据到下游 stage。

其中,每个 stage 都同时拥有一个或多个出口、入口 channel,除了第一个和最后一个 stage,其分别只有出口 channel 和入口 channel。

Telegraf 中的实现

Telegraf 采用了这种编程模式,其主要有 4 个 stage,分别为 Inputs、Processors、Aggregators 和 Outputs。

  • Inputs:负责采集原始监控指标,包括主动采集和被动采集。
  • Processors:负责处理 Inputs 收集的数据,包括去重、重命名、格式转换等。
  • Aggregators:负责聚合 Processors 处理后的数据,并对聚合后的数据计算。
  • Outputs:负责接收处理 Processors 或 Aggregators 输出的数据,并导出到其他媒介,例如文件、数据库等。

且它们彼此之间也是由 channel 相互链接的,其架构图如下所示:

img

可以看到,其整体上采用的就是 pipeline 并发编程模式,我们简单介绍下它的运作机制:

  • 第一个 stage 为 Inputs,每个 input 生成一个 goroutine,各自采集数据并扇入(fan-in)到 channel 中。
  • 第二个 stage 为 Processors,每个 processor 生成一个 goroutine,并按顺序彼此用 channel 连接。
  • 第三个 stage 为 Aggregators,每个 aggregator 生成一个 goroutine,并消费 Processors 产生的数据,并扇出(fan-out)到各个 aggregator。
  • 最后一个 stage 为 Outputs,每个 output 生成一个 goroutine,并消费由 Processors 或 Aggregators 产生的数据,并扇出到各个 output。

扇入(fan-in):多个函数输出数据到一个 channel,并由某个函数读取该 channel 直到其被关闭。

扇出(fan-out):多个函数读取同一个 channel 直到其被关闭。

插件设计

Telegraf 拥有如此众多的 input、output 以及 processor 插件,那么它是如何高效地管理这些插件呢?并且又是如何设计插件体系以应对不断激增的扩展需求呢?别急,请容我细说。

目录结构

其实,这里的插件并非通常意义上的插件(即在运行时动态加载与绑定动态链接库),而是一种基于工厂模式的变体,首先我们来看下 Telegraf 的插件目录结构:

plugins
├── aggregators
│   ├── all
│   ├── basicstats
│   ├── registry.go
...
├── inputs
│   ├── all
│   ├── cpu
│   ├── registry.go
...
├── outputs
│   ├── all
│   ├── amqp
│   ├── registry.go
...
├── processors
│   ├── all
│   ├── clone
│   ├── registry.go
...

由上可以看到,目录结构是有规律的(以下我们均以 Inputs 的插件为例,其他模块实现类似)。

  • plugins/inputs:为各个 input 插件的包目录。
  • plugins/inputs/all:通过 import 的方式引入插件模块包(主要是为了避免循环引用)。
  • plugins/inputs/registry.go:存放注册表以及相关函数。

接口声明

Telegraf 通过 interface 来声明如下 Input 接口,表示 Input:

img

接口实现

在 plugins/inputs/ 目录中创建插件,例如 cpu,实现 Input 接口:

img

注册插件

最后,我们只需要往全局注册表中注册插件的工厂函数即可:

img

如此,众多插件就被有条不紊的管理起来了。同时,扩展插件也很方便,只需实现 Input 接口并注册工厂函数即可。

参考

———————————————— 版权声明:本文为CSDN博主「尔达 Erda」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_59358648/article/details/119536943