首页 > 解决方案 > 与信号器的多个 websocket 断开连接导致应用程序池冻结

问题描述

我们在 iis 中部署了一个用 .net framework 4.6 开发的 asp.net 网站。我们使用 Signalr 2.2 实时通知客户。我们通常有 500 个客户端连接。使用的传输是 Websocket。有时会发生很多连接同时中止并出现此错误:

11:35:49.759| |ERROR| |ProcessId=17672| |ThreadId=702| |SignalR.Transports.WebSocketTransport| |OnError(e42c532d-d3d1-4649-a8c7-3d7810b2a74e, System.Net.WebSockets.WebSocketException (0x800703E3): The I/O operation has been aborted because of either a thread exit or an application request
   at System.Web.WebSockets.WebSocketPipe.<>c__DisplayClass9_0.<ReadFragmentAsync>b__0(Int32 hrError, Int32 cbIO, Boolean fUtf8Encoded, Boolean fFinalFragment, Boolean fClose)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.WebSockets.AspNetWebSocket.<DoWork>d__45`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.WebSockets.AspNetWebSocket.<>c__DisplayClass36_0.<<ReceiveAsyncImpl>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNet.SignalR.WebSockets.WebSocketMessageReader.<ReadMessageAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNet.SignalR.WebSockets.WebSocketHandler.<ProcessWebSocketRequestAsync>d__25.MoveNext())| |

问题在于,在多次断开连接期间,应用程序池似乎被“冻结”了。任何请求都会超时,我们有很多这样的错误:

11:36:32.762| |DEBUG| |ProcessId=17672| |ThreadId=1440| |Infrastructure.ExceptionHandling.ExceptionFilterAttributeHandler| |Wrapping application exception A task was canceled.| |
11:36:32.762| |ERROR| |ProcessId=17672| |ThreadId=1440| |WebApiTraceWriter| |Kind=End, Category=System.Web.Http.Filters, Message='', Operation=OnExceptionAsync, Operator=ExceptionFilterAttributeHandler, Exception=A task was canceled.| |

有时它会在几分钟后恢复工作,有时需要重新启动应用程序池才能解决问题。

更新 我注意到客户端的真正断开连接发生在连接中止后大约 15 分钟:

        public override Task OnDisconnected(bool stopCalled)
        {
            string connId = Context.ConnectionId;
            _log.InfoFormat("FOR_FILE: SignalR Server - ConnectionId [{0}] - OnDisconnected with stopCalled = {1}", connId, stopCalled.ToString());

            return base.OnDisconnected(stopCalled);
        }

当它发生时,应用程序会恢复正常工作。但为什么要在 15 分钟后?可以配置这个值吗?

标签: .netiiswebsocketsignalrapplication-pool

解决方案


解决了

我已经解决了在 Web.Config 中删除 Signalr 诊断部分的问题。

在连接了很多客户端的生产环境中,如果出现网络问题,会导致所有连接都没有立即被杀死,而是在几分钟后或应用程序池回收后。在这些分钟内,应用程序池被阻塞并且没有处理任何东西。


推荐阅读