logstash
设计了一种叫lumberjack
的日志传输。同时兼顾了性能、可靠、灵活等优点。本文从协议的角度分析一下,lumberjack
是如何设计的。
首先,日志传输是基于TCP的长连接的,这样最大限度提升了传输性能和降低了额外开销。除此之外,在协议设计上支持如下特性:
- 类似tcp滑动窗口的传输确认,保证可靠性
- 支持压缩,降低传输量
- 支持
json
格式,灵活性高 - 支持批量传输,高性能
lumberjack
有两个版本,v2版本明显优于v1,这里只讨论v2
批量和传输确认
传输确认是指,服务端可以通过返回ACK
,来告知客户端在一个批次中多少日志处理成功。一个完整的批次,称为一个window
,一个window
包含任意多条日志,每条日志具有一个序号(sequence
),在一个window中,日志的序号是唯一且有序的:
报文被传输到服务端后,服务端需根据自己实际处理成功的日志,返回相应的序号,称为ACK
。但无需返回所有成功的日志序号,只需要返回最近最大日志序号:
上图这个例子中,同时传输100条日志,服务端在处理了前30条日志后,返回ACK 30
,客户端就知道1~30号的日志处理完成了。如果在这个过程中,处理到某条日志时失败了,服务端应停止处理剩余的日志,并立刻返回处理成功的最大日志序号,这样客户端就知道在一个批次的日志处理中,究竟多少成功,多少失败,进而记录并重传。
可以看到这种传输确认跟tcp的差错重传机制有些类似。
支持压缩
日志大多是文本字符串,将文本进行压缩,可以极大的提高传输效率(当然发送端和接收端会增加一些CPU开销)。lumberjack
通过在window中增加一个compress
层,把里层的日志数据统一压缩来实现。具体的压缩算法基于deflate,使用libz
即可。
总结
传输系统的设计讲究高效、可靠。lumberjack
协议借鉴了tcp滑动窗口设计,在应用层兼顾了高效和可靠。更多关于协议的细节,请参考logstash的lumberjack协议解析
网友评论