极速精简 Go 版 Logstash

简介: 极速精简 Go 版 Logstash

前言

今天来介绍 go-zero 生态的另一个组件 go-stash。这是一个 logstash 的 Go 语言替代版,我们用 go-stash 相比原先的 logstash 节省了2/3的服务器资源。如果你在用 logstash,不妨试试,也可以看看基于 go-zero 实现这样的工具是多么的容易,这个工具作者仅用了两天时间。

整体架构

先从它的配置中,我们来看看设计架构。

Clusters:
  - Input:
      Kafka:
        # Kafka 配置 --> 联动 go-queue
    Filters:
     # filter action
      - Action: drop            
      - Action: remove_field
      - Action: transfer      
    Output:
      ElasticSearch:
        # es 配置 {host, index}

看配置名:kafka 是数据输出端,es 是数据输入端,filter 抽象了数据处理过程。

对,整个 go-stash 就是如 config 配置中显示的,所见即所得。

image.png

启动

stash.go 的启动流程大致分为几个部分。因为可以配置多个 cluster,那从一个 cluster 分析:

  1. 建立与 es 的连接【传入 es 配置】
  2. 构建 filter processorses 前置处理器,做数据过滤以及处理,可以设置多个】
  3. 完善对 es 中 索引配置,启动 handle ,同时将 filter 加入handle【处理输入输出】
  4. 连接下游的 kafka,将上面创建的 handle 传入,完成 kafkaes 之间的数据消费和数据写入

MessageHandler

在上面架构图中,中间的 filter 只是从 config 中看到,其实更详细是 MessageHandler 的一部分,做数据过滤和转换,下面来说说这块。

以下代码:https://github.com/tal-tech/go-stash/tree/master/stash/handler/handler.go

type MessageHandler struct {
 writer  *es.Writer
 indexer *es.Index
 filters []filter.FilterFunc
}

这个就对应上面说的,filter 只是其中一部分,在结构上 MessageHandler 是对接下游 es ,但是没有看到对 kafka 的操作。

别急,从接口设计上 MessageHandler 实现了 go-queueConsumeHandler 接口。

这里,上下游就串联了:

  1. MessageHandler 接管了 es 的操作,负责数据处理到数据写入
  2. 对上实现了 kafkaConsume 操作。这样在消费过程中执行 handler 的操作,从而写入 es

实际上,Consume() 也是这么处理的:

func (mh *MessageHandler) Consume(_, val string) error {
 var m map[string]interface{}
  // 反序列化从 kafka 中的消息
 if err := jsoniter.Unmarshal([]byte(val), &m); err != nil {
  return err
 }
 // es 写入index配置
 index := mh.indexer.GetIndex(m)
  // filter 链式处理【因为没有泛型,整个处理都是 `map进map出`】
 for _, proc := range mh.filters {
  if m = proc(m); m == nil {
   return nil
  }
 }
 bs, err := jsoniter.Marshal(m)
 if err != nil {
  return err
 }
 // es 写入
 return mh.writer.Write(index, string(bs))
}

数据流

说完了数据处理,以及上下游的连接点。但是数据要从 kafka -> es ,数据流出这个动作从 kafka 角度看,应该是由开发者主动 pull data from kafka

那么数据流是怎么动起来?我们回到主程序 https://github.com/tal-tech/go-stash/blob/master/stash/stash.go

其实 启动 整个流程中,其实就是一个组合模式:

func main() {
 // 解析命令行参数,启动优雅退出
 ...
  // service 组合模式
 group := service.NewServiceGroup()
 defer group.Stop()
 for _, processor := range c.Clusters {
  // 连接es
    ...
  // filter processors 构建
    ...
    // 准备es的写入操作 {写入的index, 写入器writer}
  handle := handler.NewHandler(writer, indexer)
  handle.AddFilters(filters...)
  handle.AddFilters(filter.AddUriFieldFilter("url", "uri"))
    // 按照配置启动kafka,并将消费操作传入,同时加入组合器
  for _, k := range toKqConf(processor.Input.Kafka) {
   group.Add(kq.MustNewQueue(k, handle))
  }
 }
 // 启动这个组合器
 group.Start()
}

整个数据流,就和这个 group 组合器有关了。

group.Start()
 |- group.doStart()
  |- [service.Start() for service in group.services]

那么说明加入 groupservice 都是实现 Start()。也就是说 kafka 端的启动逻辑在 Start()

func (q *kafkaQueue) Start() {
 q.startConsumers()
 q.startProducers()
 q.producerRoutines.Wait()
 close(q.channel)
 q.consumerRoutines.Wait()
}
  1. 启动 kafka 消费程序
  2. 启动 kafka 消费拉取端【可能会被名字迷惑,实际上是从 kafka 拉取消息到 q.channel
  3. 消费程序终止,收尾工作

而我们传入 kafka 中的 handler,上文说过其实是 Consume,而这个方法就是在 q.startConsumers() 中执行的:

q.startConsumers()
 |- [q.consumeOne(key, value) for msg in q.channel]
  |- q.handler.Consume(key, value)

这样整个数据流就彻底串起来了:

image.png

总结

作为 go-stash 第一篇文章,本篇从架构和设计上整体介绍 go-stash ,有关性能和为什么我们要开发一个这样的组件,我们下篇文章逐渐揭晓。

https://github.com/kevwan/go-stash

关于 go-zero 更多的设计和实现文章,可以持续关注我们。

https://github.com/zeromicro/go-zero

相关文章
|
存储 消息中间件 JSON
(21)go-micro微服务logstash使用
(21)go-micro微服务logstash使用
345 0
|
7月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
372 2
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
9月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
561 1
|
11月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
|
9月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
568 0
|
9月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
400 0
|
9月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
447 0
|
9月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
500 0

热门文章

最新文章