背景与动机

2016 年,随着公司业务规模的快速增长,日志量和监控需求呈指数级上升。我们面临着这样一个问题:如何在海量的日志数据中,高效地收集、传输、存储和分析日志信息?

当时,团队内部对日志收集方案产生了分歧。一部分同事推荐 Apache Flume,另一部分则倾向于 ELK 技术栈中的 Logstash。为了做出科学的决策,我决定对这两个工具进行系统的性能对比测试。这篇博客记录的,就是那段日子里我做的三组测试的完整过程和结论。

日志收集架构选型

测试环境说明

在开始测试之前,先交代一下测试环境的基本情况:

  • 服务器配置:4核 CPU,8GB 内存,千兆网卡
  • 日志来源:Nginx access.log
  • 测试工具:ab(Apache Benchmark)
  • 监控指标:CPU 负载、请求延时、数据收集效率

测试一:CPU 负载对比

第一个测试的目标是观察两种工具在端口监控场景下对系统资源的占用情况。毕竟,一个日志收集工具如果本身就吃掉了大量的 CPU 资源,那它就没有资格被部署到生产环境中。

Flume

端口监控时,Java 进程的 CPU 负载在 10%~13% 左右。

Flume CPU 负载

从监控图表可以看出,Flume 的 CPU 占用相对平稳,波动不大。这得益于 Flume 的 Channel 机制——它通过内存或文件 Channel 来缓冲数据,避免了对下游系统的瞬时冲击。

Logstash

端口监控时,Java 进程的 CPU 负载在 8%~10% 左右。

Logstash CPU 负载

相比较而言,在 CPU 负载方面,Logstash 表现更佳。它比 Flume 低了大约 2-3 个百分点。虽然这个数字看起来不大,但在生产环境中,这意味着在同等硬件条件下,Logstash 可以处理更多的日志量。

原因分析:Logstash 基于 JRuby 运行在 JVM 上,其 Pipeline 模型经过了深度优化。而 Flume 的 Agent 架构虽然灵活,但在轻量级场景下,其多组件(Source-Channel-Sink)的设计带来了一定的额外开销。

测试二:请求延时对比

第二个测试关注的是日志收集对业务请求的延时影响。我们模拟了 10000 次页面请求,通过 Nginx 生成 access.log,然后观察两种工具从日志产生到收集完成的整体耗时。

Flume

请求 shenzhenlong.newvip.youku.com 页面,Nginx 生成的 access.log 日志,请求 10000 次,耗费时间为 1768.13 秒,平均每请求一次耗时 0.1768 秒

Flume 10000次请求耗时

Logstash

同样的测试条件下,请求 10000 次,耗费时间为 1637.93 秒,平均每请求一次耗时 0.1637 秒

Logstash 10000次请求耗时

相比较而言,在请求延时方面,Logstash 同样更佳。每万次请求可以节省约 130 秒的时间,相当于每个请求快了约 13 毫秒。在高并发的生产环境中,这个差距会被放大,直接影响用户体验。

深入分析:Logstash 在处理 Nginx 日志时,其 Grok 过滤器虽然功能强大,但在纯转发场景下并非瓶颈。真正影响延时的是数据从产生到写入存储的整个链路。Logstash 的 Pipeline 设计使其在处理速度上有一定的优势。

测试三:不同写入方式的效率对比

第三个测试是最有意思的一个。我们对比了 Flume 在两种不同日志收集机制下的表现:一种是直接通过 RPC 写入 Flume Agent,另一种是先写入硬盘日志文件,再由 Flume 从文件收集。

方式一:RPC 直接写入 Flume

利用 RPC 方式直接写入 Flume,请求 10000 次:

  • 发送时间:8.922 秒

Flume RPC 发送时间

  • 收集时间:55.007 - 45.471 = 9.536 秒

Flume RPC 收集时间

效率计算:9.536 - 8.922 = 0.614 秒。这意味着每收集到 10000 条数据,发送到 Flume Agent 的额外用时仅为 0.614 秒,响应速度非常快。

方式二:先写硬盘日志,再由 Flume 收集

利用写 Log 方式先直接写入硬盘,然后 Flume 收集,请求 10000 次:

  • 发送时间:1.006 秒

Flume 写Log发送时间

  • 收集时间:57.172 - 53.001 = 4.171 秒

Flume 写Log收集时间

效率计算:4.171 - 1.006 = 3.165 秒。说明响应时间为每收集到 10000 条数据,Flume Agent 收集到数据用时为 3.165 秒。

测试三分析与对比

对比项 RPC 直写 写 Log 后收集
发送时间 8.922s 1.006s
收集时间 9.536s 4.171s
额外开销 0.614s 3.165s
总体效率 更高 较低

从数据可以看出:

  1. RPC 直写方式的延时更低:每 10000 次日志生成,RPC 直写比写硬盘方式效率快约 2.5 秒。这是因为 RPC 跳过了磁盘 I/O 这一环节,数据直接通过网络传输到 Agent。
  2. 写 Log 方式的发送时间更短:因为应用只需将日志写入本地文件,无需等待网络传输,所以发送时间短。但 Flume 从文件收集数据的过程中,存在文件轮询、解析等额外开销。
  3. RPC 方式更适合实时性要求高的场景:如果业务对日志的实时性要求较高,RPC 直写是更好的选择。

注意:目前 PHP 调用实现 RPC 的方式需要进一步实现,本次测试三暂时使用 Java 语言测试。后续需要推进 PHP RPC 客户端的适配工作。

日志收集方式对比总结

综合结论与建议

经过这三组系统性的测试,我得出了以下结论和建议:

1. CPU 负载方面

Logstash 的 CPU 占用略低于 Flume(8%-10% vs 10%-13%),在资源敏感的环境中,这个差距值得考虑。

2. 请求延时方面

Logstash 在处理日志时的整体延时更低,每万次请求可以节省约 130 秒。

3. 收集机制方面

  • RPC 直写效率最高,额外开销仅 0.614 秒/万次。
  • 写 Log 后收集虽然发送时间短,但整体收集耗时更长。
  • 建议采用 RPC 方式直接写入 Agent 的方案,做出 Demo 后与现有 Logstash 的收集方式做全面的性能、负载、效率对比。

4. 技术选型的思考

在做技术选型时,不能只看单一指标。我们需要综合考虑:

  • 团队技术栈:如果团队对 Java 生态更熟悉,Flume 可能更容易上手和维护。
  • 数据规模:小规模的日志收集,两者差异不明显;但当日志量达到 TB 级别时,每一个百分点的效率差异都会被放大。
  • 运维成本:Logstash 与 Elasticsearch、Kibana 天然集成,如果已经在使用 ELK 栈,Logstash 是自然的选择。
  • 扩展性:Flume 的 Source-Channel-Sink 架构在复杂数据流场景下更为灵活,可以方便地接入多种数据源和输出目标。

写在最后

这次测试让我深刻地认识到:没有最好的工具,只有最适合的工具。Flume 和 Logstash 各有优劣,选择哪一个取决于具体的业务场景、技术栈和团队能力。

技术的进步永不停歇。如今回看 2016 年的这篇测试,ELK 技术栈已经发展到了 Elastic Stack 8.x 版本,Flume 也逐渐被 Filebeat、Fluentd 等更轻量的工具所替代。但测试方法论本身——明确目标、控制变量、量化指标、综合分析——依然是我们在面对技术选型时应该遵循的基本原则。