起因
什么时候触发背压
ELK 直接传输 vs 外部消息队列
0. 准备测试环境
1. 外部消息队列
2. 直接传输
如何观测背压事件?
外部消息队列
直接传输
结论
起因
我们在日常使用 ELK 链路的时候,经常会碰到一个问题,由于链路涉及的组件较多,一旦当其中某些组件出现问题,就会出现“事件风暴”,如果没有做好相关的告警或者资源管控,很可能会使链路发生崩溃。
在官方文档中,我们可以看到一个相关的描述:
真的有这么丝滑吗,我不信(鲁豫脸
然而,在我们实践过程中并没有图中描绘得如此理想,很多情况下,在后端 ES 写入出现问题时,前端输入(如 filebeat)并不会减慢采集速率,导致中间的缓存队列(Redis)存储爆满,在没有做好资源隔离时,引发其他问题。
所以我们就来仔细研究一下 ELK 背压原理,看看如何才能调试出一条伸缩自如、百折不挠的 ELK 链路。
什么时候触发背压
Logstash 内部会有一个 buffer 区域缓存一定量的事件,这个队列可以存储在内存或磁盘。一旦当这个队列缓存跑满,Logstash 会反向给事件输入端(Input)施加 "back pressure"(不返回 ACK),限制流量流入。
代码语言:javascript复制# 缓存落盘
queue.type: persisted
queue.max_bytes: 8gb
类似我们给这个队列配置 8gb 的缓存,当事件队列里全都是 unACKed
事件,并且缓存达到了 8gb,Logstash 就不再接受任何事件推送,直到将队列内的事件被消费重新恢复。
对于 Input 端而言,官方提供的组件也都实现了类似逻辑,例如 Filebeat,当没有收到 output ACK 事件数量积累到 最大限制(默认 4096) 时,会停止读取文件,直到组件内部缓存队列能够被消费,所以理论上,只要能够通过 TCP 互相连接的组件,ELK 提供的组件应该都是可以实现背压能力的。
ELK 直接传输 vs 外部消息队列
经典的 ELK 链路中,我们通常为了会扩展 buffer,在 Beats 和 Logstash 之间增加一个中间队列(例如 Kafka、Redis),相比较直接使用 ELK 链路传输,在背压问题上又有哪些优劣呢?
首先是是否都能触发背压?
在上文中提到的,我们使用 Redis 是无法正常触发背压的,理论上说不通。于是经过一番搜索,发现filebeat 需要使用 >=6.4
的版本,而我们正好用的是 6.3