logstash設(shè)計了一種叫lumberjack的日志傳輸。同時兼顧了性能、可靠、靈活等優(yōu)點。本文從協(xié)議的角度分析一下,lumberjack是如何設(shè)計的。

首先,日志傳輸是基于TCP的長連接的,這樣最大限度提升了傳輸性能和降低了額外開銷。除此之外,在協(xié)議設(shè)計上支持如下特性:
- 類似tcp滑動窗口的傳輸確認(rèn),保證可靠性
- 支持壓縮,降低傳輸量
- 支持
json格式,靈活性高 - 支持批量傳輸,高性能
lumberjack有兩個版本,v2版本明顯優(yōu)于v1,這里只討論v2
批量和傳輸確認(rèn)
傳輸確認(rèn)是指,服務(wù)端可以通過返回ACK,來告知客戶端在一個批次中多少日志處理成功。一個完整的批次,稱為一個window,一個window包含任意多條日志,每條日志具有一個序號(sequence),在一個window中,日志的序號是唯一且有序的:

報文被傳輸?shù)椒?wù)端后,服務(wù)端需根據(jù)自己實際處理成功的日志,返回相應(yīng)的序號,稱為ACK。但無需返回所有成功的日志序號,只需要返回最近最大日志序號:

上圖這個例子中,同時傳輸100條日志,服務(wù)端在處理了前30條日志后,返回ACK 30,客戶端就知道1~30號的日志處理完成了。如果在這個過程中,處理到某條日志時失敗了,服務(wù)端應(yīng)停止處理剩余的日志,并立刻返回處理成功的最大日志序號,這樣客戶端就知道在一個批次的日志處理中,究竟多少成功,多少失敗,進(jìn)而記錄并重傳。
可以看到這種傳輸確認(rèn)跟tcp的差錯重傳機制有些類似。
支持壓縮
日志大多是文本字符串,將文本進(jìn)行壓縮,可以極大的提高傳輸效率(當(dāng)然發(fā)送端和接收端會增加一些CPU開銷)。lumberjack通過在window中增加一個compress層,把里層的日志數(shù)據(jù)統(tǒng)一壓縮來實現(xiàn)。具體的壓縮算法基于deflate,使用libz即可。

總結(jié)
傳輸系統(tǒng)的設(shè)計講究高效、可靠。lumberjack協(xié)議借鑒了tcp滑動窗口設(shè)計,在應(yīng)用層兼顧了高效和可靠。更多關(guān)于協(xié)議的細(xì)節(jié),請參考logstash的lumberjack協(xié)議解析