SignalR .NET客户端断开连接

smi*_*tra 9 signalr signalr-hub signalr.client

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

  • 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事件,并发现,当断开并重新连接会触发该事件,但不能当它不重新连接.

然后我们遇到了这个帖子:客户经常重新连接

并决定将所有内容升级到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不支持Windows 7上的WebSockets

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

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

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

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

编辑:更多信息:

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

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

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

其中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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

  • 使用SiteCode = ABCD执行登录过程.
  • SignalR服务器:经过身份验证

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

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

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

另外,日志事件:

LogEvent("Successful login for connectionid: " & connectionId & ". Context. User: " & userId, EventLogEntryType.Information)
Run Code Online (Sandbox Code Playgroud)

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

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

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

smi*_*tra 4

最后,我们只是创建了一个简单的“PINGING”函数。每 15 分钟就会调用一次。逻辑如下:

  1. SignalR 客户端有一个计时器,每 15 分钟调用一次服务器 PING 方法。
  2. 服务器调用客户端的 PINGCLIENT 方法作为响应。
  3. 在客户端上的下一个 PING 计时器事件中(15 分钟后),我们检查是否收到响应。如果没有,我们将暂停所有活动并重新初始化集线器连接。然后重新启动 PINGING 计时器。

因此,虽然我们放弃了尝试找出原因,但我们有一个解决方法来管理“服务器到客户端”连接丢失的情况。请注意,这是对 signalR 中内置的重新连接逻辑的补充。

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