我正在关注 ELK 上的这篇文章:Building Logging System in Microservice Architecture with ELK Stack and Serilog .NET Core,在这种架构中,serilog 记录到 Logstash,然后将 logstash 推送到 Elastic 搜索,如果弹性搜索不可达或如果 logstash 服务关闭或如果网络宕机或系统宕机,总之我要去哪里,我如何确保我的日志在所有场景中都不会丢失,日志也应该离线可用,我想先存储在日志中文件,然后将日志从文件处理到弹性搜索,但是文件会在一段时间内增长,然后我必须注意没有重复的消息并且消息也需要删除,最重要的是没有读写文件时出现死锁的情况,能否请您帮我了解一下ELK是否小心,如果我使用fluend或fluentbit而不是logstash,它们更好吗??
代码:
var log = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.Http("http://localhost:8080")
.CreateLogger();
while (true)
{
var customer = Customer.Generate();
log.Information("{@customer} registered", customer);
Thread.Sleep(1000);
}
输出:
[13:56:02 INF] {"FirstName": "Lourdes", "LastName": "Kreiger", "SSNumber": "350-11-7869", "$type": "Customer"} registered
[13:56:03 INF] {"FirstName": "Desmond", "LastName": "Balistreri", "SSNumber": "929-58-1854", "$type": "Customer"} registered
...
使用 ELK 发送日志
input {
http {
#default host 0.0.0.0:8080
codec => json
}
}
# Separate the logs
filter {
split {
field => "events"
target => "e"
remove_field => "events"
}
}
# Send the logs to Elasticsearch
output {
elasticsearch {
hosts => "elasticsearch:9200"
index=>"customer-%{+xxxx.ww}"
}
}
答案 0 :(得分:1)
您有两个可能导致数据丢失的主要故障点,logstash 和 elasticsearch 之间的通信以及您的服务和 logstash 之间的通信。
logstash 和 elasticsearch 之间的通信
当发送数据到elasticsearch时,logstash默认使用管道的input
块和filter
块之间的内存队列,这个队列的存在是为了在logstash无法与之通信的情况下存储事件弹性搜索。
这个内存队列有固定大小的 1000 个事件,所以如果你每秒有很多事件,它没有多大帮助。您可以更改管道以使用 persisted queue,此队列将执行与内存中队列相同的操作,但它会写入 logstash 服务器中的文件,您可以更改文件大小以存储更多事件.
如果持久化队列已满,elasticsearch 仍然关闭,logstash 将停止接受新的事件,队列何时会填满完全取决于队列的大小、事件的大小和事件的速率,但持久化队列是您可以避免在 logstash 和 elasticsearch 之间丢失数据的方法之一。
服务和logstash之间的通信
如果您的服务无法与 logstash 通信,那么您需要在其上实现一些逻辑以避免数据丢失。如何做到这一点完全掌握在您的手中。
您可以复制 logstash 使用的持久队列并将未发送到 logstash 的事件写入文件,然后在 logstash 返回时重播这些事件。
这将添加许多您需要自己实现的额外内容。
替代方案
我认为最好的方法是将日志写入日志文件,然后使用 filebeat 将这些日志发送到 logstash,如果您不想在 logstash 中使用任何过滤器,甚至可以直接发送到 elasticsearch ,filebeat 可以在输出服务不可达的情况下自动重试发送日志,并跟踪已发送或未发送的内容。
由于您使用的是 dotnet,因此您可以使用 log4net 进行日志记录,它会处理日志记录部分,并在达到指定大小时轮换您的日志。