SignalR Redis 内存泄漏

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

我有一个使用 .NET Framework 4.6.1 实现的控制台应用程序,如此处所述。

.NET框架4.6.1 Microsoft.AspNet.SignalR 版本 2.4.2 StackExchange.Redis 版本 2.1.58

我们使用 StackExchangeRedis Resolver 并且已经设置了 DefaultMessageBufferSize = 32。 当我断开并重新连接设备时,我会体验到内存的增加。

Startup.cs

public void Configuration(IAppBuilder appBuilder)
{
    GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(connectionTimeout);
    GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(disconnectTimeout);
    GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(keepAlive);
    GlobalHost.Configuration.DefaultMessageBufferSize = defaultMessageBufferSize;
    appBuilder.MapSignalR($"/{GetAppSettingValue("SignalRAddress")}", new HubConfiguration()
    {
        EnableDetailedErrors = TraceMode,
        EnableJavaScriptProxies = true,
        EnableJSONP = true,
        Resolver = GlobalHost.DependencyResolver.UseStackExchangeRedis(
            new RedisScaleoutConfiguration(SignalRedisConnection, GetAppSettingValue("AppName"))
        )
   });
   appBuilder.UseNinjectMiddleware(CreateKernel);
}

private static IKernel CreateKernel()
{
    Kernel.Bind<IXXX>().To<XXX>().InSingletonScope();
    
    ...
    
    return Kernel;
}

程序.cs

class Program
{
    static void Main(string[] args)
    {
        HostFactory.Run(x =>
            {
                x.Service<SignalRService>(s =>
                {
                    string servicename = "Web Socket Service";
                    x.SetServiceName(servicename);
                    x.SetDescription("...");
                    x.SetDisplayName(servicename);
                    x.SetInstanceName(servicename);
                    s.ConstructUsing(n => new SignalRService());
                    s.WhenStarted((service, hostControl) => service.Start(hostControl));
                    s.WhenStopped((service, hostControl) => service.Stop(hostControl));
                });

                x.EnableShutdown();
                x.RunAsLocalSystem();
                x.UseAssemblyInfoForServiceInfo();
                x.SetStartTimeout(TimeSpan.FromMinutes(2));
                x.SetStopTimeout(TimeSpan.FromMinutes(2));
                x.DependsOnEventLog();
            });
    }
}

internal class SignalRService : ServiceControl
{
    public SignalRService()
    {
        Task.Run(() =>
        {
            WebApp.Start<Startup>(Address);
            ...

        }).Wait();
        
        _timer = new Timer(MyTimerAsync, null, 0, Convert.ToInt32(Startup.LostDeviceTimer.TotalMilliseconds));
    }
        
    private async void MyTimerAsync(object stateInfo)
    {
        var broadcaster = BroadcastManager.Instance;
        
        ...
    }
}

BrokerHubManager.cs

public class BrokerHubManager : Hub
{
    private readonly BroadcastManager _broadcaster;
    
    public BrokerHubManager() : this(BroadcastManager.Instance)
    {
        ...
    }

    public BrokerHubManager(BroadcastManager broadCaster)
    {
        _broadcaster = broadCaster;
    }
}

BroadcastManager.cs

public class BroadcastManager
{
    private static readonly Lazy<BroadcastManager> _instance = new Lazy<BroadcastManager>(
        () => new BroadcastManager(GlobalHost.ConnectionManager.GetHubContext<BrokerHubManager>()));
    
    private BroadcastManager(IHubContext context)
    {
        ...
    }

    public static BroadcastManager Instance
    {
        get { return _instance.Value; }
    }
}

Retained Memory Retained Object

我尝试实现如此处所示的处置,但我仍然收到错误。

问题在于 BroadcastManager._instance 没有按照第二张图片所示进行处置。 你有什么建议吗?

.net memory-leaks signalr idisposable signalr-backplane
1个回答
0
投票

按照 Guru Stron 的建议,我修改了代码如下,但内存泄漏问题仍然存在。

Startup.cs

public void Configuration(IAppBuilder appBuilder)
{
    ...
   appBuilder.UseNinjectMiddleware(CreateKernel);
}

private static IKernel CreateKernel()
{
    Kernel.Bind<IBroadcastManager>().To<BroadcastManager>().InSingletonScope();
    Kernel.Bind<IHubContext>().ToMethod(context =>
            GlobalHost.ConnectionManager.GetHubContext<BrokerHubManager>()
        ).WhenInjectedInto<IBroadcastManager>();
    
    ...
    
    return Kernel;
}

程序.cs

class Program
{
    static void Main(string[] args)
    {
        ...
    }
}

internal class SignalRService : ServiceControl
{
    private IBroadcastManager _broadcaster;
    
    public SignalRService()
    {
        Task.Run(() =>
        {
            WebApp.Start<Startup>(Address);

            _broadcaster = Startup.Kernel.Get<IBroadcastManager>();
            ...

        }).Wait();
        
        _timer = new Timer(MyTimerAsync, null, 0, Convert.ToInt32(Startup.LostDeviceTimer.TotalMilliseconds));
    }
        
    private async void MyTimerAsync(object stateInfo)
    {
        _broadcaster.XXX();
        
        ...
    }
}

BrokerHubManager.cs

public class BrokerHubManager : Hub
{   
    public BrokerHubManager()
    {
        ...
    }
}

BroadcastManager.cs

public class BroadcastManager : IBroadcastManager
{
    private IHubContext _context;
    
    private BroadcastManager(IHubContext context)
    {
        _context = context;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.