介绍炬鲸 OBSERVE 日志采集链路的性能与背压设计:解析并发、有界队列、磁盘缓冲如何在洪峰下避免丢数据,给出关键调优参数与压测容量规划方法。
日志采集最怕两件事:高峰丢日志、采集器把应用拖垮。炬鲸 OBSERVE 的采集层把「采集—解析—富化—投递」拆成独立阶段,用有界队列和落盘缓冲衔接。这篇文章讲它的背压设计,以及怎么调参、怎么做容量规划。
一条日志从文件到可检索,经过四段:tail 读取、正则/Grok 解析、字段富化、批量投递。瓶颈通常不在 tail,而在解析——一条多行 Java 堆栈或一个大 JSON 对象,解析开销可能是单行纯文本的几倍。定位瓶颈不要靠猜,直接看采集器暴露的 stats 指标:tail_files_open、parse_errors、buffer_queued、dropped_events。如果 dropped_events 持续增长,说明下游消化不了,该调背压参数,而不是盲目加机器;buffer_queued 高位不回落、投递耗时升高,则说明是检索集群写入变慢,不是采集端的问题。
采集器用「有界内存队列 + 落盘缓冲」两级背压。内存队列默认 4096 条,写满后新事件进入磁盘缓冲文件;磁盘缓冲按 512MB 分片、最多保留 48 小时,超过上限才丢弃并打点。这样后端短暂抖动(比如检索集群在做分片均衡)时,数据先落盘,恢复后自动重放,不会丢。两个要注意的点:磁盘缓冲要放在独立的、有足够 IOPS 的数据盘上,别和系统盘共用;dropped_events 一旦非零就要告警,别等用户报障才发现。另外落盘缓冲不是免费的,它用磁盘空间换可靠性,如果后端长期跟不上,缓冲最终也会满,所以它解决的是「短暂抖动」,不是「长期容量不足」。
采集器配置示例:
pipeline:
tail:
max_open_files: 512
read_buffer_bytes: 262144
parse:
workers: 8
multiline_max_lines: 500
buffer:
type: memory+disk
memory_queue_size: 8192
disk_chunk_bytes: 536870912
disk_retention_hours: 48
sink:
batch_size: 1000
flush_interval_ms: 1000
retry_backoff_ms: 500
经验值:workers 等于 CPU 核数;multiline_max_lines 别设太大,否则一条坏日志会占住解析线程;batch_size 越大吞吐越高但延迟也越高,实时告警场景 flush 间隔控制在 1 秒内;retry_backoff_ms 用指数退避,避免后端恢复瞬间被重试打垮。
上线前做回放压测:抽 100 万条生产日志,按 2 倍峰值速率灌入,看 buffer_queued 是否回落、dropped_events 是否为零。容量按「峰值 EPS × 平均单条字节数」估算,留 30% 余量。先确定哪些场景丢数据不可接受,再倒推队列和磁盘缓冲尺寸,比事后加机器便宜。