filebeat 的源码分析

1. Architecture

filebeat 是基于libbeat 来build 的一个开源库, filebeat 总共分5个部分:
1. input 在给定的路径上寻找文件,并启动扫割进程来收割文件的数据
2. harvester: 收割机, 读一个文件,然后发送一个事件给spooler
3. spooler: 收集harvester 的发送过来的事件,等待一定时间将事件flush 给publisher
4. publisher: 写数据到network, 然后通知registrar
5. registrar: 记录文件数据读取的位置

我们来看看filebeat 的架构:
这里写图片描述

从上面的架构可以看出一个prospector(input) 可以scan 多中log, 每一个log file 对应了一个Harvester.


2. Run Step

接下来我们从走读source code 来看看filebeat 的启动, filebeat src 下面有一个main.go 是filebeat 的入口, main 的入口处正如跟程序一样, 刚开始去解析cli 的参数, filebeat 把这块code封装在cmd 的package 中, filebeat 中将beat 的实现放在了filebeat/beater.go 将实例带入 libbeat/cmd package 中, cmd 中的实例实现在cmd/instance 中的beat.go, instance/beat.go 中分别实现了BeatConfig, Setup, Run 等等。
我们来看看Run 的code:

 func Run(name, idxPrefix, version string, bt beat.Creator) error {
     return handleError(func() error {
         defer func() {
             if r := recover(); r != nil {
                 logp.NewLogger(name).Fatalw("Failed due to panic.",
                     "panic", r, zap.Stack("stack"))
             }
         }()
         b, err := NewBeat(name, idxPrefix, version)
         if err != nil {
             return err
         }
         return b.launch(bt)
     }())
 }

首先我们会根据name 来create 一个Beat 对于filebeat 来说name 自然就是filebeat 了. 这里主要通过launch 来launch 一个beat 的. launch 的参数其实是一个函数,这个函数就是filebeat/cmd 那边带来的(也就是filebeat 的中的New 函数)
launch 中有三步非常重要:
a. Init Beat, 这个将会去Initialize plugin 和解析configuration
b. 利用filebeat 的New 函数作为参数来create 一个beater, createBeater 将返回一个beater , 并且会根据configuration 去加载pipeline (也就是相应的publisher, ElasticSearch/Logstash/redis/console 等等)
c. 将b 中create 的beater Run 起来.
重点我们来看b 和c

2.1 PipeLine Load

pipeline 的Load 主要在publisher 的pipeline package 中, 下面是load 的一段主要code:

queueBuilder, err := createQueueBuilder(config.Queue)
out, err := loadOutput(beatInfo, reg, outcfg)
p, err := New(beatInfo, reg, queueBuilder, out, settings)

从上面可以知道,我们create output 主要有三步,create queue, loadOutput, 然后根据queue 和out 创建pipeline 返回去。

然后我们接下去看一下loadOutput 这个函数, 它主要call

out, err := outputs.Load(beatInfo, outStats, outcfg.Name(), outcfg.Config())

这个根据beat 的信息,out observer 还有out put name 以及out put config 来Load 一个out. outputs 中包括多个output plugin

这里写图片描述

这只是粗线条的说明了pipeline 加载的code. 接下来我们来看beater Run 的code

2.2 Filebeat Run

libbeat 中的Launch 中最后一步就是beater的run, 对于Filebeat 来说当然就是 filebeat/beater 的Run 函数了, 这个函数中最主要的两步是

  • registrar 的create 和start

  • crawler 的 create 和start


我们主要看看crawler 了, 这个在架构中没有体现出来,在code 层面上这个是相当重要的, 对于filebeat 来说.crawler负责具体的日志采集工作。它会根据配置文件启动多个prospector,每个prospector处理一类日志文件类型,有着一组独立的配置。prospector会启动一个prospectorer干主要的活。根据默认配置,这个prospectorer会是ProspectorLog类型的。ProspectorLog类型的prospectorer会扫描目标路径下匹配的文件,根据registry里存储的状态判断每个文件。如果之前处理过,调用harvestExisingFile;否则调用harvestNewFile。前者会判断对应的harvester是否还在运行。这两个函数都涉及到一个Harvester的创建。随便一提,registry是registrar创建之后传递给crawler的,里面是文件的处理状态记录.
对于ProspectorLog来说,它在创建Harvester时调用的是harvester/log.go中的Harvest方法。该方法首先创建一个LineReader, 我们来看看调用的关系了

这里写图片描述
现在我们随着FileEvent(以下简称为事件)来到spooler里面。一进来,就看到事件们在这里排起了长龙。spooler接到事件后,不急着发出去,而是排进队列中。如果队列(长度取决于spool_size,默认2048)已满,调用flush方法把事件刷到publisher里面。此外配置的flush时间idle_timeout(默认5s)到时后,也会调用flush方法。publisher 将数据会送到一个叫registry, registry 会将数据做持久化并更新进度。
这里写图片描述
那publisher 又是怎么工作的?其实publisher 中有一个Client, 这个Client由libbeat/publisher/publish.go的Connect函数创建的, 我们可以以ElasticSearch 为例看看他的的代码结构:
这里写图片描述
以上我只是粗略的分析了一下filebeat 的source code, 具体的还要慢慢琢磨。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论

打赏作者

david_zhang228

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值