Azure Web 作业和 SignalR 内存泄漏

Azure Web Jobs and SignalR memory leak

所以我有一些网络作业偶尔会连接到信号中心并广播消息。下面只是其中的一个示例,在本例中,它是一个简单的 Web 开发作业,其 TimerTrigger 属性每 20 秒连续设置为 运行。就像下面代码中显示的那样。

    public static void Main()
    {

        JobHostConfiguration config = new JobHostConfiguration();
        config.Tracing.ConsoleLevel = TraceLevel.Verbose;
        config.UseTimers();
        if (config.IsDevelopment)
        {
            config.UseDevelopmentSettings();
        }
        var host = new JobHost(config);
        host.RunAndBlock();
    }

    public static void ProcessPush([TimerTrigger("00:00:20", RunOnStartup = true)] TimerInfo timerInfo, TextWriter log)
    {
        // Send a signalr message to the Hub
        try
        {            
            SendMessageToHub(log);
        }
        catch (Exception e)
        {
            log.WriteLine($"WebJob Push Exception: {e.Message}");
        }
    }

    private static async Task SendMessageToHub(TextWriter log)
    {
            var hub = new HubConnection(CloudConfigurationManager.GetSetting("MyWebSite"));
            var proxy = _hub.CreateHubProxy("MyHub");

            log.WriteLine("WebJob Push: Sending message to SignalR Hub.");
            if (_hub.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Disconnected)
            {
                await _hub.Start();
            }
            await _proxy.Invoke("BroadcastMessage");
            log.WriteLine("WebJob Push: Sent message to SignalR Hub.");
    }

托管网站和信号中心的服务器上的内存始终在增加。在调查网站上的 IIS 日志时,似乎有大量 POST 消息在同一秒到达网站,使用长轮询。然后它等待了一会儿,然后又收到了另一批消息的狂轰滥炸。顺便说一下,这也会让 IIS 服务器上的 CPU 发疯。此 post 的底部是 IIS 日志条目的示例。

我希望能够以与常规脉冲消息一致的方式从 Web 作业发送信号器消息(我们想扩展 Web 作业 - 请原谅它 运行现在在计时器上)。

亲切的问候,

斯蒂芬

示例 IIS 日志条目 - 请注意它们都在同一秒内进入,而不是相隔 20 秒:

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=TBbNVDpndk0riu8UvVzbGJrWjYIo7eMLcP4lk7ABV74OBMbZRTJrCRL1bzsPxpd1Tyle2rS3tV2JJrigninhu880ml51Xers76PPDX0Hf97dTBYR4k %2BVc2V9KAmiGt0p&messageId=d-80E0087-B%2C7D%7CEz%2C0%7CE0%2C0 443 - 104.210.116.149 SignalR.Client.NET45/2.2.1.0+(Microsoft+Windows+NT+6.2 .9200.0) - 200 0 0 5343

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=KYwQXpNrPIU21NXMa0So5u42EwXTcMlGyLqL3tettun4WHLfO %2BhPd%2BcPeZPmfe6KKvQL13XIU1W5fApuTv0XN5XFPoNUmyBjhhISoqodwcZeu3QKmkbaXcpHMtE&messageId=d-80E0087-B%2C7D%7Cav%2C0%7Caw%2C2 443 - 104.210.116.149 SignalR.Client.NET45/2.2.1.0+(Microsoft+Windows+NT +6.2.9200.0) - 200 0 0 10641

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=nO %2BPZ8M5JJOpiobpJUV5%2FZvQyEKYjp%2FOuqQ%2F0Bkq05TKRJZfeI%2FD%2BxRyPC7EsAAjXVqJr05PksorlMWrXocGkskfVsLU2Qvtx%2Fi1O8hU5lNz4KcoSc%2Bkv%2BlDpr2AZBLv&messageId=d-80E0087-B%2C7D%7CFB%2C0%7CFC%2C0 443 - 104.210.116.149 SignalR.Client.NET45/2 .2.1.0+(微软+Windows+NT+6.2.9200.0) - 200 0 0 18282

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=wiGSRiNHdd7crhkcAMd %2FWy%2F3qGRZ5WdBm%2BdbR3b7aTbtpB8aaBGDil%2FqAWha6Si5eEohsUmCxAU4Pkefy%2BNoxoG9fgYC4R66ErXIShyBUcsNLWo1AyH5zGDk7bFvme3E&messageId=d-80E0087-B%2C7D%7CE9%2C0%7CE_%2C0 443 - 104.210.116.149 SignalR.Client.NET45/2.2.1.0+(Microsoft+Windows+NT+6.2.9200.0) - 200 0 0 11360

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=hEJ1b0 %2Bz2eeyC8IvYmOV3ffZ%2FAFQiQpEnJLUmCZTEVDLwcgOqhyQbQnu0R29sazp6BxcK4WsDhSbEdg2Sh4wMBSZjQtKMzASr2Fa2eY2HGgoVJcfDOMixQX2FCqfa%2BmP&messageId=d-80E0087-B%2C7D%7CFD%2C0%7CFE%2C0 443 - 104.210.116.149 SignalR.Client.NET45/2.2.1.0+(Microsoft+Windows +NT+6.2.9200.0) - 200 0 0 15798

2016-11-15 23:10:35 POST /signalr/poll clientProtocol=1.4&transport=longPolling&connectionData=[%7B%22Name%22:%22MyHub%22%7D]&connectionToken=2UsU63IHgaNO %2BBYmoamsKxFq7Vv3uaGigvR1NrGnntVnAbTg2C0%2BVXZnA9aT8siqpkBv%2Fo8avvvNTSBfQD77IspaO6jOnSU8rXMXDU2Vr6ojkWr%2Fwt1LFsdNy3%2BHpDGC&messageId=d-80E0087-B%2C7D%7CEv%2C0%7CEw%2C0 443 - 104.210.116.149 SignalR.Client.NET45/2.2.1.0+(Microsoft+Windows+NT+6.2.9200.0) - 200 0 0 11844

等等,等等

UPDATE - 明确停止集线器连接似乎已经处理了孤立客户端(或同一 Web 作业客户端的多余客户端)。特别是,添加 _hub.Stop();调用代理后。

对某些人来说这听起来很明显,答案是确保我们在向其发送消息后停止集线器连接。下面是带有注释包围的附加行的代码。

这似乎与浏览器客户端不同,客户端在一段时间不活动后会断开连接。 webjob 客户端会留下来,并继续对网站进行轮询。因此,每次触发 webjob(通过计时器或通过读取 azure 队列或主题中的消息)时,它都会不断生成新客户端并保留该连接。

在 webjob 中,你必须明确地停止连接,否则内存和 CPU 会逐渐崩溃。

private static async Task SendMessageToHub(TextWriter log)
{
        var hub = new HubConnection(CloudConfigurationManager.GetSetting("MyWebSite"));
        var proxy = _hub.CreateHubProxy("MyHub");

        log.WriteLine("WebJob Push: Sending message to SignalR Hub.");
        if (_hub.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Disconnected)
        {
            await _hub.Start();
        }
        await _proxy.Invoke("BroadcastMessage");
        /////////////////////////////////////////////////////////////
        // Stopping the hub connection is necesssary in a web job  //
        _hub.Stop();   
        /////////////////////////////////////////////////////////////
        log.WriteLine("WebJob Push: Sent message to SignalR Hub.");
}