SignalR .NET客户端断开连接

我们遇到了一个有趣的问题 . 以下是我们的设置:

在Windows Server 2012上

  • SignalR Server(ASP.NET MVC应用程序) .

  • Sencha HTML5应用程序(SignalR客户端)位于同一服务器(Windows Server 2012)上 .

  • Windows Server 2008 R2服务器上的.NET Windows服务 . 这也充当SignalR客户端 .

最初我们使用SignalR 0.5.3 - 当我们开始观察到Windows服务与信号R服务器的连接中断时 . 频率范围从每几分钟到每几个小时 . 它在大多数情况下重新连接,但偶尔无法重新连接,导致Windows服务每两天丢失一次连接 . 但它没有固定的模式 . 它与服务器重启/备份等无关 . 我们在Windows服务中添加日志记录以监视客户端连接上的StateChanged事件,并发现事件在断开连接并重新连接时被触发,但在没有重新连接时则触发 .

然后我们遇到了这个帖子:client constantly reconnecting

并决定将所有内容升级到SignalR 1.0.1(我们不得不在某些时候这样做) . Windows服务也升级到框架4.5(来自Framework 2.0),现在引用新的Microsoft.AspNet.SignalR.Client.dll . 这也允许我们(使用新添加的连接属性)确定Windows服务实际上使用ServerSentEvents协议 . 在Windows Server 2012计算机上安装相同的Windows服务使用WebSockets协议 . 这符合这个主题:SignalR .NET Client doesn't support WebSockets on Windows 7

但是,Windows Server 2008 R2服务器上的服务行为没有更改 . 它仍然断开连接并重新连接,偶尔会失去连接 . 由于一些限制,我们无法使用Windows Server 2012进行Windows服务,并且无法使用较旧的操作系统 . 这并不是说使用websockets协议的Windows服务可以解决我们所有的问题(我们没有彻底测试过) .

我们尝试的第三件事是从GitHub获取源代码并编译它并升级服务(SignalR Server和客户端) - 这样做是为了确保我们获得带有任何潜在错误修复的最新副本 .

但它没有帮助 . 我们现在处于一种我们认为已经筋疲力尽的选择 . 建议将不胜感激 . 谢谢 .

=====================================

EDIT: MORE INFORMATION:

好的,现在我们有更多的信息 . 我们在Windows服务(SignalR Client)中添加了一些代码,每30分钟登录一次SignalR服务器(用于测试连接) .

以下是客户端每30分钟发生的事情:

WriteEvent(Now(), "INFO", "PING", "Performing logon procedure with SiteCode = " & msSiteCode & ".")
trans.Invoke("login", New String() {msSiteCode, "", "SERVER", "", ""})

其中trans是从Hub继承的服务器端类的实例,而WriteEvent基本上是写入日志文件的跟踪 .

客户端也有一个'isLoggedIn'方法,如下所示:

Private Sub isLoggedIn(ByVal bLoggedIn As String)
        If bLoggedIn Then
            WriteEvent(Now(), "INFO", "", "SignalR Server: Authenticated")           
        Else
            WriteEvent(Now(), "ERROR", "", "SignalR Server: Authentication failed")
        End If
End Sub

在服务器端,我们有登录方法:

Public Sub login(ByVal sAccount As String, _
                     ByVal sCompanyCode As String, _
                     ByVal sClientId As String, _
                     ByVal sPassword As String, _
                     ByVal sModuleCode As String)
       Try
            'Some code omitted that validates the user and sets bValidated.

            If bValidated Then
                'Update user in cache
                ConnectionCache.Instance.UpdateCache(userId, Context.ConnectionId, UserCredential.Connection_Status.Connected)
                Clients.Caller.isLoggedIn(True)

                Dim connectionId As String = ConnectionCache.Instance.FindConnectionId(userId)
                LogEvent("Successful login for connectionid: " & connectionId & ". Context. User: " & userId, _
                         EventLogEntryType.Information)
            Else
                Clients.Caller.isLoggedIn(False, results)
            End If
        Catch ex As Exception
            LogEvent("Login: " & ex.Message, EventLogEntryType.Error)
        End Try
End Sub

如果我们查看客户端日志文件,每30分钟我们会得到以下日志条目:

  • 使用SiteCode = ABCD执行登录过程 .

  • SignalR Server:已通过身份验证

因此我们知道正在调用登录服务器端方法,并且还调用了isLoggedIn客户端方法 .

但是,在某些时候,在调用服务器端方法时,不会调用isLoggedIn客户端方法 . 所以每30分钟,我们开始只获得一个条目:

  • 使用SiteCode = ABCD执行登录过程 .

另外,日志事件:

LogEvent("Successful login for connectionid: " & connectionId & ". Context. User: " & userId, EventLogEntryType.Information)

在服务器端登录方法中写入服务器端日志 . 所以 Clients.Caller.isLoggedIn(True) 按预期调用,但我们在客户端看不到 .

所以我想我们正在看的是客户端始终能够访问服务器并能够调用服务器端(登录)功能,但服务器无法调用客户端(isLoggedIn)函数,这开始发生在一点 .

此外,这可能是.NET客户端特有的,因为我很确定我们没有看到我们的HTML5 / javascript客户端发生这种情况 .

回答(1)

2 years ago

最后,我们创建了一个简单的“PINGING”功能 . 每15分钟调用一次 . 逻辑如下:

  • SignalR Client有一个定时器,每15分钟调用一次服务器PING方法 .

  • Server在客户端调用客户端的PINGCLIENT方法作为响应 .

  • 在客户端的下一个PING计时器事件中(15分钟后),我们检查是否得到了响应 . 如果我们没有,我们暂停所有活动并重新初始化Hub连接 . 然后重新启动PINGING计时器 .

因此,虽然我们放弃了试图弄清楚原因是什么,但我们有一个解决方法来管理“服务器到客户端”连接的丢失 . 请注意,这是signalR中内置重新连接逻辑的补充 .

我们还维护日志,平均而言,这种情况发生(客户端不会从服务器返回PING),可能每天一次 .