【问题标题】:SignalR .NET client disconnectingSignalR .NET 客户端断开连接
【发布时间】:2014-04-30 06:49:07
【问题描述】:

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

  • Windows Server 2012 上的 SignalR Server(一个 ASP.NET MVC 应用程序)。
  • Sencha HTML5 应用程序(SignalR 客户端)在同一台服务器 (Windows Server 2012) 上。
  • .NET Windows 服务在 Windows Server 2008 R2 服务器上。这也充当 SignalR 客户端。

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

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

并决定将所有内容升级到 SignalR 1.0.1(无论如何我们都必须在某个时候这样做)。 Windows 服务也升级到框架 4.5(从框架 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 服务器和客户端) - 这样做是为了确保我们获得包含任何潜在错误修复的最新副本。

但这并没有帮助。我们现在处于一个我们觉得我们已经用尽了我们的选择的地步。建议将不胜感激。谢谢。

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

编辑:更多信息:

好的,现在我们有了更多信息。我们在 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 服务器:已通过身份验证

所以我们知道是调用了login服务端方法,同时也调用了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 提要 www.myget.org/F/aspnetwebstacknightly/ 上试用客户端的夜间包。我们现在有客户端日志记录(Connection 有一个 TextWriter 属性 connection.Trace)。您可以使用它来查看发生了什么以及为什么网络上没有运行。
  • 谢谢。我们现在记录了更多事件,并使用更多信息更新了原始问题。
  • 你需要客户端日志而不是服务器端日志。
  • 你能解决这个问题吗?
  • 你解决过这个问题吗?

标签: signalr signalr-hub signalr.client


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 2012-04-05
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多