为什么你应该了解 Loggie

语言: CN / TW / HK

你可能对日志并不感兴趣。

不过没关系,本文也不打算介绍Loggie如何采集日志。

首先请不要被Loggie的名称限制了思维,我想重新定义一下:

什么是Log?

从本质上,Log即为Data。而Data,在我们平时的开发中无处不在。

引用知名经典野猪书《Designing Data-Intensive Applications》(还没看过这本书的请不要错过)里的一句话:

现今很多应用程序都是数据密集型(data-intensive) 的,而非计算密集型(compute-intensive) 的。因此CPU很少成为这类应用的瓶颈,更大的问题通常来自数据量、数据复杂性、以及数据的变更速度。

不管我们是CRUD boy或者YAML工程师,恐怕写代码的时候最常接触和思考的,还是如何设计各种数据模型,如何处理内存、磁盘或网络上的字节,通常这些过程中,会涉及到协议编解码(JSON/ProtoBuf),数据存储(SQL/NoSQL)与通信(HTTP/RPC),消息传递(MQ)等等。

但是,我们在工作中,往往会更加关注项目的业务逻辑,忽略背后的技术本质和抽象,以及工程化的难题与挑战。长期以来,很容易成为某些第三方库的熟练封装工,框架API的机械使用者,别人嘴里的「调包侠」。

如何避免陷入这种困境?一个好的办法是选择一个合适的开源项目,从项目里学习总结和提炼,尝试对其中的代码进行修改、补充或者优化。

真正合适的选择其实并不多,当然你也能猜到,这里我向你推荐Loggie。

因为,Loggie有着直观、通用的数据链路模型:source → interceptor → sink,典型的数据密集型应用,没有太多的业务属性,易于扩展开发,极致简单但却又包罗万象。

Loggie是什么?

仅从日志的场景来解释,Loggie(http://github.com/loggie-io/loggie/) 是一个基于Golang的轻量级、高性能、云原生日志采集Agent和中转处理Aggregator,支持多Pipeline和组件热插拔,提供了:

🔨 一栈式日志解决方案:同时支持日志中转、过滤、解析、切分、日志报警等

☁ 云原生的日志形态:快速便捷的容器日志采集方式,原生的Kubernetes动态配置下发

🔑 生产级的特性:Loggie吸收了我们长期的大规模运维经验,形成了全方位的可观测性、快速排障、异常预警、自动化运维能力

但需要再次强调的是,Loggie里的Log只是Data或者Events在一种具体场景下的称号,采集日志只是其中一个叫file source的组件,Loggie里还有很多其他的source/interceptor/sink:

所以,格局大点,我更愿意描述Loggie为:CloudNative Events Connector And Processor

(云原生的数据连接器,连接了各种数据源,可以对各种数据流进行处理、转换与路由)

从使用形态上Loggie可划分为:

  • Sidecar形态:部署在每个业务容器一起,用于采集容器日志在内的数据
  • Agent形态: 每个节点一个或者每个Pod一个,用于采集日志或者其他数据
  • Aggregator形态: 用于中转、转发和处理,可独立部署成集群

基于简单直接的Source → Interceptor → Sink 模型,以及多Pipeline设计,Loggie可以用在很多的场景:

  • 数据采集: 采集容器日志、节点日志,采集Prometheus metrics、Kubernetes Events等
  • 数据中转: 作为中转机去做数据的聚合、转发、分流
  • 数据处理: 进行流式数据的切分、转换、处理
  • 日志报警: 进行异常日志的检测与报警

......

但是,这些都不重要,重要的是:

为什么你应该了解一下Loggie?

Loggie是一个“麻雀虽小,五脏俱全”的项目,特别如果你是一个Gopher,日常写Golang或者正在学习,Loggie简直就是为你量身打造。

考虑到Loggie的使用场景,Loggie需要追求极致的轻量化、极致的性能、极致的稳定性以及可维护性。Data-intensive的各种case,在Loggie中都可能有集中的体现。

比如:

  • 队列模型的知识:如何保证队列里的事务或者at least once语义?在队列中如何实现重试、限流、去重、背压?如何设计一个持久化队列?
  • 插件化设计模型:各种动态的配置(validate/defaults),各种组件的解偶与可插拔
  • 极致的性能追求:如何写出高性能的Golang代码,如何做到面向GC编程,这其中有哪些常见的bad taste?
  • 可观测性:Loggie致力于可观测性的统一采集与转发,所以这里有prometheus metrics、openTelemetry等等。同时如何做好项目自身的可观测性?这关系到项目是否能够真的在线上稳定运行,以及长期运行的易用性与可维护性
  • Golang Runtime的一些入门,如何成为熟练使用pprof的一把好手,如何快速进行排障,以及在项目中怎么做持续的profile?
  • 流式处理:Loggie是如何实现一个轻量级的流式处理功能,怎么去实现一个简单的带有逻辑判断的DSL?
  • Kubernetes Operator:这里有分布式的Controller,可选的集中式Operator,还有自动的sidecar注入,以及基于K8s编程的历史与演进
  • 各类文件系统的知识:通过探究Loggie最常用的file source设计,以及file sink和持久化队列,你能够了解如何高性能的和文件系统打交道
  • 各种中间件:Loggie的各种source/sink,有对各种中间件SDK的选型,不管是Kafka、Elasticsearch以及后续的Clickhouse, Pulsar等网红中间件,你都可以找到可供参考的code example以及使用的最佳实践
  • 自动化测试: 在Golang项目里如何集成静态代码检查,如何做e2e、集成、Fuzz、压测自动化测试?如何处理各种依赖的外部组件?

如果你深入了解Loggie后,你会发现,平时里遇到的项目,或多或少都带有一点Loggie的影子。因为他们都遵循数据密集型应用本质的设计,都可以参考类似的解决思路,像江湖中的某种武功绝学,我们平时练习了太多花里胡哨的招式,却一直没有领悟到大师们秘而不宣的心法,Loggie可能就是那个隐藏在石碑上的口诀。

另外,如果你在某个时刻,需要进行数据的传输和处理,请第一时间想到Loggie,看看Loggie能不能满足你的需求。如果不能,可以考虑一下快速开发一个Source、Sink或Interceptor组件,复用Loggie的能力,可以避免大量重复的开发工作,比如:

  • 在Kubernetes集群中可方便、快速的使用CRD下发配置,并且支持自动reload、支持指定集群,无需考虑部署、配置更新等问题
  • 依赖Loggie提供传输过程的稳定性和可靠性,保证at-least-once和重试机制,避免数据丢失,以及数据量过多或过大造成的隐患
  • 使用Loggie提供的一系列监控指标,比如队列长度、传输延迟、发送QPS等,可快速接入Prometheus,同时还可使用一些系统内置的快速排障的接口与能力
  • 使用可插拔的Interceptor可用于自定义的数据处理、格式转换等,避免过多的定制化代码开发

当然,Loggie还是一个很年轻的项目,正式开源后的这段时间,每天都有很多人在问各种问题、提各种需求、给各种建议,Loggie还有太多的功能亟待研发,充满了各种可能性,如果你感兴趣,欢迎来提issues加入讨论,提PR为Loggie添砖加瓦。

接下来将有一系列文章,分享我们在开发Loggie的一些思考和收获,我挑了几个通用的、有意思的主题组成了这个系列,姑且命名为《A byte of Loggie》,本文可为序。

所以,实际上这是一个“挂着羊头卖狗肉”的系列,Loggie只是一个引子,引出的是在Loggie实践中的沉淀、引申、抽象和总结。

最后,第一篇预告:《A byte of Loggie: 各式各样的队列及其方法论》

请加入你的延迟队列。

相关阅读:

云原生日志架构实践:网易数帆开源Loggie的三生三世

网易X工行:云原生日志系统 Loggie 正式开源!

Loggie项目地址:http://github.com/loggie-io/loggie/

作者简介: 傅轶,网易数帆 轻舟日志平台负责人、架构师。目前专注网易数帆轻舟云原生日志平台研发,致力于云原生技术及其生态体系建设和商业化落地,对Kubernetes、Serverless、可观测性等有较深入研究,具有丰富的云原生分布式架构设计开发经验与项目实践。