在使用Logstash做日志收集时,一个常见场景是通过syslog 插件来收集网络设备或安全设备的日志。
但是当你去搜索 logstash syslog plugin 时,可能会发现搜索引擎或者 ChatGPT 给出的答案却是udp 插件或tcp 插件。
这时就会有疑问:
- syslog 插件和 tcp/udp 插件到底有什么差异?
- 为什么官方的 syslog 插件性能很差?
- 实际生产环境该用哪个插件?
本文尝试分析 syslog 插件与 tcp/udp 插件的差异,并给出最佳实践。
syslog 插件的实现
Logstash 提供了一个syslog插件,它支持同时监听 TCP 和 UDP。
只需要配置端口即可,无需指定协议。
部分代码实现如下:
def udp_listener(output_queue)
@logger.info("Starting syslog udp listener", :address => "#{@host}:#{@port}")
@udp.close if @udp
@udp = UDPSocket.new (IPAddr.new(@host).ipv6? rescue nil) ? Socket::AF_INET6 : Socket::AF_INET
@udp.do_not_reverse_lookup = true
@udp.bind(@host, @port)
while !stop?
payload, client = @udp.recvfrom(65507)
metric.increment(:messages_received)
decode(client[3], output_queue, payload)
end
ensure
close_udp
end # def udp_listener
...
...
def tcp_listener(output_queue)
@logger.info("Starting syslog tcp listener", :address => "#{@host}:#{@port}")
@tcp = TCPServer.new(@host, @port)
@tcp.do_not_reverse_lookup = true
while !stop?
socket = @tcp.accept
@tcp_sockets << socket
metric.increment(:connections)
Thread.new(output_queue, socket) do |output_queue, socket|
tcp_receiver(output_queue, socket)
end
end
ensure
close_tcp
end # def tcp_listener
可以看到:
- UDP :通过
recvfrom接收数据 - TCP :每个连接都起一个线程处理
也就是说,syslog 插件的 TCP 处理是基于多线程模型 。 这在并发连接数多的情况下,性能会急剧下降。
udp 插件的实现
再看 udp 插件的实现:
def udp_listener(output_queue)
@logger.info("Starting UDP listener", :address => "#{@host}:#{@port}")
...
# some code
...
while !stop?
next if IO.select([@udp], [], [], 0.5).nil?
# collect datagram messages and add to inputworker queue
@queue_size.times do
begin
payload, client = @udp.recvfrom_nonblock(@buffer_size)
break if payload.empty?
push_data(payload, client)
rescue IO::EAGAINWaitReadable
break
end
end
end
ensure
if @udp
@udp.close_read rescue ignore_close_and_log($!)
@udp.close_write rescue ignore_close_and_log($!)
end
end
这里采用的是 IO 复用 (select/非阻塞 IO) ,而不是线程 per connection。 因此在高并发 UDP 场景下性能更好。
tcp 插件的实现
TCP 插件则是基于 Netty 封装的高性能事件驱动框架:
java_import 'org.logstash.tcp.InputLoop'
Netty 能够高效处理海量连接,相比 syslog 插件的多线程实现,性能提升巨大。
syslog 插件的额外开销
除了 I/O 模型上的差异,syslog 插件还会对日志进行 协议解析 ,比如调用 grok 规则对 syslog message 做拆解。而 tcp/udp 插件只是单纯地收取消息,不做协议解析。 因此:
- syslog 插件: 收集 + 解析 (功能更多,但性能差),但是现在的syslog很多都不会遵守相关的协议规定。
- tcp/udp 插件: 只收集 (需要后续手动解析,但性能好)
结论与推荐实践
- 性能优先 :建议使用
tcp或udp插件来收集 syslog 日志,再通过grok或dissect插件解析。 - 简单配置 :如果设备较少、日志量不大,可以直接用 syslog 插件。
- 生产环境最佳实践 :
- 用 udp/tcp 插件收集日志
- 在 pipeline 中使用 grok/dissect 做 syslog 格式解析
- 输出到 Elasticsearch / Kafka 等存储系统