首页 > 解决方案 > Serilog - 多线程日志记录会阻止应用程序取消

问题描述

我无法正常关闭从多个线程登录到 Serilog ElasticSearch 接收器的 .NET Core 应用程序。下面是一个最小的工作示例:

Program.cs

using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;

public class Program
{
    public static async Task Main() =>
        await new HostBuilder()
            .UseConsoleLifetime()
            .ConfigureLogging((context, logging) => logging.AddSerilog(
                new LoggerConfiguration()
                    .WriteTo.Console()
                    .WriteTo.Elasticsearch(
                        nodeUris: "http://example.com:9200",
                        indexFormat: "derp-{0:yyyy.MM.dd}",
                        typeName: "_doc"
                    )
                .CreateLogger(), dispose: true)
            )
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<DerpService>();
            })
        .Build()
        .RunAsync();
}

DerpService.cs

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class DerpService : BackgroundService
{
    private readonly ILogger<DerpService> _logger;
    public DerpService(ILogger<DerpService> logger)
    {
        _logger = logger;
    }
    protected override async Task ExecuteAsync(CancellationToken stoppingToken) =>
        await Task.WhenAll(Enumerable
            .Range(0, 100)
            .Select(i =>
                Task.Run(() =>
                {
                    while (!stoppingToken.IsCancellationRequested)
                    {
                        _logger.LogInformation($"Task {i} is here!");
                    }
                }, stoppingToken)
        ));
}

当我运行这个应用程序时,Serilog 立即开始向控制台写入一大堆Task i is here!消息,但几分钟内没有任何内容记录到 ElasticSearch。一旦 ElasticSearch 日志启动,它们就会随着应用程序的继续运行而逐渐落后。此外,应用程序的内存消耗会随着Serilog.Events.LogEvent实例而激增,似乎没有限制。最后,当我尝试Ctrl+C在控制台窗口中取消应用程序时,控制台日志停止,内存消耗逐渐减少,但应用程序仍然存活了几分钟,大概是在 Serilog 咀嚼LogEvents 的积压发送到弹性搜索。

很明显,我正在用比以往更多的并发日志来锤击 Serilog ElasticSearch 接收器,但是对于任何具有日志记录的多线程应用程序来说,这些似乎都是潜在的烦人问题。具体来说:

  1. ElasticSearch 是否具有可以处理的最大日志记录速率?有什么好方法可以让它更快吗?
  2. 我认为 .NET Core 通用主机应该在 5 秒后自动关闭。ElasticSearch 接收器阻止主机关闭应用程序怎么办?
  3. 在指示应用程序关闭后,有什么方法可以强制取消 Serilog Ctrl+C(假设我不关心剩余的日志事件)?

提前致谢!

标签: c#multithreadingelasticsearchserilog

解决方案


推荐阅读