Serilog.ILogger.TaskScheduler 引发了异常。引发了“System.OutOfMemoryException”类型的异常

问题描述 投票:0回答:1

我有一个 .NET 4.8 WindowService,它使用 Autofac 进行依赖注入并使用 Serilog 进行日志记录。

我的 Serilog 记录器注册为

builder.Register<ILogger>((c, p) =>
{
     return new LoggerConfiguration()
                    .MinimumLevel.Verbose()
                    .WriteTo.Logger(logger => logger
                        .Filter.ByIncludingOnly(e => e.Level == Serilog.Events.LogEventLevel.Verbose || e.Level == Serilog.Events.LogEventLevel.Debug)
                        .WriteTo.Async(asyncLog => asyncLog.File(ApplicationConstants.ApplicationLogPath + "\\Trace\\Trace-.txt", Serilog.Events.LogEventLevel.Verbose, ApplicationConstants.ApplicationLogTemplate, rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true, fileSizeLimitBytes: 10000000, shared: true)))
                    .WriteTo.Logger(logger => logger
                        .Filter.ByExcluding(e => e.Level == Serilog.Events.LogEventLevel.Verbose && e.Level == Serilog.Events.LogEventLevel.Debug)
                        .WriteTo.Map("LogContext", "Log",
                        (LogContext, wt) => wt.Async(asyncLog => asyncLog.File(ApplicationConstants.ApplicationLogPath + $".\\Logs\\{LogContext}-.txt", Serilog.Events.LogEventLevel.Information, ApplicationConstants.ApplicationLogTemplate, rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true, fileSizeLimitBytes: 10000000, shared: true))))
                    .CreateLogger();
});

我使用工厂模式来解析使用相同接口的多个类。他们的依赖关系注册如下

 builder.RegisterType<HandleA>().As<IHandler>().Keyed<IHandler>("HandleA");
 builder.RegisterType<HandleB>().As<IHandler>().Keyed<IHandler>("HandleB");

服务不断处理数据,然后根据类型解决对运行时的依赖关系,如下所示

case "A":
    return ContainerManager.Container.ResolveKeyed<IHandler>("HandleA");
case "B":
    return ContainerManager.Container.ResolveKeyed<IHandler>("HandleB");

其中 ContainerManager.Container 是一个静态 IContainer 变量,当所有依赖项都在服务启动时构建时,该变量包含容器。

现在接口IHandler的类的实现是

public class HandleA: IHandler
{
     private ILogger _fileLogger;
     public HandleA(ILogger fileLogger)
     {
            _fileLogger = fileLogger;
     }
}

此时解析,代码抛出错误

An exception was thrown while activating Service.HandleA
 -> ?:Serilog.ILogger.An exception was thrown by a TaskScheduler.Exception of type 'System.OutOfMemoryException' was thrown.
at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)     
at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)     
at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)     
at Autofac.Core.Resolving.Middleware.RegistrationPipelineInvokeMiddleware.Execute(ResolveRequestContext context, Action`1 next)     
at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)     
at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)    
 at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)    
 at Autofac.Core.Resolving.Middleware.ScopeSelectionMiddleware.Execute(ResolveRequestContext context, Action`1 next)     
 at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)    
 at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)    
 at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)   
 at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)   
 at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)  
 at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request)   
 at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)    
 at Autofac.Core.Container.ResolveComponent(ResolveRequest request)   
 at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)    
 at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)     
 at Autofac.ResolutionExtensions.ResolveKeyed[TService](IComponentContext context, Object serviceKey, IEnumerable`1 parameters)

注意: 当偶尔解决依赖关系时,这种情况不会每次都会发生,并且只会在服务器上重现(8333 次中的 690 次),而不是在本地。

由于其偶发性,我无法持续监控任务管理器来检查内存使用情况。

服务器有 32 个核心和 64-128GB RAM,并且托管有多个服务和 API,所以问题肯定是在我这边。

.net memory-leaks serilog
1个回答
0
投票

其中一个非常可疑的地方是您注册记录器的方式。默认情况下,Autofac 使用 Instance Per Dependency 策略,因此您将为每个依赖项创建一个记录器,据我所知,这不是 Serilog 应该使用的方式。

考虑在启动时构建一次记录器并将其注册为实例:

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .WriteTo.Logger(logger => logger
        .Filter.ByIncludingOnly(e => e.Level == Serilog.Events.LogEventLevel.Verbose || e.Level == Serilog.Events.LogEventLevel.Debug)
        .WriteTo.Async(asyncLog => asyncLog.File(ApplicationConstants.ApplicationLogPath + "\\Trace\\Trace-.txt", Serilog.Events.LogEventLevel.Verbose, ApplicationConstants.ApplicationLogTemplate, rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true, fileSizeLimitBytes: 10000000, shared: true)))
    .WriteTo.Logger(logger => logger
        .Filter.ByExcluding(e => e.Level == Serilog.Events.LogEventLevel.Verbose && e.Level == Serilog.Events.LogEventLevel.Debug)
        .WriteTo.Map("LogContext", "Log",
            (LogContext, wt) => wt.Async(asyncLog => asyncLog.File(ApplicationConstants.ApplicationLogPath + $".\\Logs\\{LogContext}-.txt", Serilog.Events.LogEventLevel.Information, ApplicationConstants.ApplicationLogTemplate, rollingInterval: RollingInterval.Day, rollOnFileSizeLimit: true, fileSizeLimitBytes: 10000000, shared: true))))
    .CreateLogger();

// ...

builder.RegisterInstance<ILogger>(logger);

或者更好地考虑使用类似 Serilog.Extensions.Autofac.DependencyInjection.

© www.soinside.com 2019 - 2024. All rights reserved.