SignalR .NET客户端断开连接

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

  • SignalR服务器(一个ASP.NET MVC应用程序),运行在Windows Server 2012上。
  • Sencha HTML5应用程序(SignalR客户端)运行在同一台服务器上(Windows Server 2012)。
  • .NET Windows服务运行在Windows Server 2008 R2服务器上,并且也作为SignalR客户端。

最初,我们使用的是SignalR 0.5.3,当时我们发现Windows服务与SignalR服务器的连接会断开。这种情况的频率从每几分钟到每几个小时不等。它大多数情况下可以重新连接,但偶尔无法重新连接,导致Windows服务每隔两天失去一次连接。但是并没有固定模式。这与服务器重启/备份等无关。我们在Windows服务中添加了日志来监视客户端连接的StateChanged事件,发现当其断开和重新连接时,该事件会被触发,但在无法重新连接时则不会触发。

然后我们看到了这个主题:client constantly reconnecting

并决定将所有内容升级到SignalR 1.0.1(无论如何都必须这样做)。Windows服务也升级到框架4.5(从Framework 2.0),现在引用新的Microsoft.AspNet.SignalR.Client.dll。这也允许我们(使用新添加的连接属性)确定Windows服务实际上正在使用ServerSentEvents协议。安装同样的Windows服务在Windows Server 2012机器上,将使用WebSockets协议。这符合此主题:SignalR .NET Client doesn't support WebSockets on Windows 7

然而,在Windows Server 2008 R2服务器上,服务的行为并没有改变。它仍然会断开和重新连接,并偶尔失去连接。由于一些限制,我们无法在Windows Server 2012上使用Windows服务,而被困在旧操作系统上。这并不意味着使用WebSockets协议的Windows服务将解决所有问题(我们没有彻底测试过)。

我们尝试的第三件事是从GitHub获取源代码并编译并升级服务(SignalR服务器和客户端)——这样做是为了确保我们获得最新的版本以及任何潜在的错误修复。

但是没有帮助。我们现在到了一个无法再继续的地步。非常感谢任何建议。谢谢。

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

编辑:更多信息:

好的,现在我们有了更多信息。我们将一些代码添加到Windows服务(SignalR客户端)中,以每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服务器:已验证

因此,我们知道已调用登录服务器端方法,并且已经调用了isLoggedIn客户端方法。

但是,在某个时刻,尽管已调用服务器端方法,但未调用isLoggedIn客户端方法。所以每30分钟,我们开始只收到一个条目:

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

此外,还有日志事件:

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

在服务器端登录方法中,写有服务器端日志。因此,Clients.Caller.isLoggedIn(True)被如预期般调用,但我们在客户端看不到它。

所以我想我们正在研究的是客户端总是能够访问服务器并能够调用服务器端(登录)函数,但服务器无法调用客户端的(isLoggedIn)函数,并且这种情况在某个时候开始发生。

此外,这可能是特定于.NET客户端的问题,因为我相当确定我们没有在我们的HTML5/javascript客户端中看到这种情况发生。


如果你愿意,可以在这个myget feed:www.myget.org/F/aspnetwebstacknightly/ 上尝试使用客户端的夜间版本包。现在我们有了客户端日志记录(连接具有TextWriter属性connection.Trace)。您可以使用它来查看发生了什么以及为什么在您的网络上行为异常。 - davidfowl
谢谢。我们现在已经记录了更多的事件,并更新了原始问题,提供了更多的信息。 - smitra
你需要在客户端记录日志,而不是在服务器端记录。 - davidfowl
你已经解决了这个问题吗? - zaitsman
你解决了这个问题吗? - Dave Alperovich
请查看最近添加的答案。 - smitra
1个回答

4
最终,我们创建了一个简单的“PINGING”功能。每15分钟调用一次该功能。
具体逻辑如下:
  1. SignalR客户端有一个定时器,每15分钟调用服务器上的PING方法。
  2. 服务器响应时,在客户端调用客户端的PINGCLIENT方法。
  3. 在客户端的下一个PING定时器事件(15分钟后),我们检查是否收到响应。如果没有收到响应,我们暂停所有活动并重新初始化Hub连接。然后重新启动PINGING计时器。
因此,尽管我们放弃了试图找出原因,但我们有了一个解决方案来处理“服务器到客户端”连接丢失的情况。请注意,这是SignalR内置重新连接逻辑的补充。
我们还记录日志,平均每天发生一次此类情况(客户端未从服务器收到PING)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接