【问题标题】:SignalR: The connection id is in the incorrect format. How to deal with it when the session expires?SignalR:连接 ID 的格式不正确。 session过期时如何处理?
【发布时间】:2014-05-27 22:26:03
【问题描述】:

我提出了一个众所周知的 SignalR 问题,当用谷歌搜索“连接 ID 的格式不正确”时会给出多个结果。但是我找不到适合我需要的解决方案。建议的所有解决方案都是相同的:在客户端的 javascript 中停止 signalR。但是,我需要以某种方式停止或处理服务器端的错误。

示例:用户登录,SignalR 启动,一切正常,他单击注销(就在注销之前,我覆盖了 javascript 事件并停止 SignalR)。没有错误。

另一个例子:用户登录,SignalR 启动,用户等待一段时间会话结束。他点击了一些东西,他被扔到了登录页面。但是,SignalR 现在注意到用户的身份已更改并抛出此错误连接 ID 格式不正确。添加其中一些发生的情况,我的 IIS Worker 以 100% 的 CPU 工作,从而导致服务器崩溃。稍加修改的示例包括 SignalR ping 服务器并再次看到会话已结束并因此引发异常。

我应该如何处理这样的问题?有没有办法从服务器端为某些客户端停止 SignalR?或者也许是不同的东西?也许我可以让 SignalR 以某种方式停止依赖身份?我相信人们一定已经以某种方式解决了这个问题。我在我的项目中使用表单身份验证和 MVC4。 SignalR 的版本是 1.0.0。我知道它不是最新的,但我怀疑如果它是最新的它会有什么好处。或者也许有人有证据证明我错了?

我正在从我的 IIS 日志中添加错误信息以防万一:

Exception information: 
    Exception type: InvalidOperationException 
    Exception message: 

Server stack trace: 
   at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
   at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
   at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary`2 environment)
   at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary`2 environment)
   at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
   at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)

Exception rethrown at [0]: 
   at Microsoft.Owin.Host.SystemWeb.Utils.<>c__DisplayClass1.<GetRethrowWithNoStackLossDelegate>b__0(Exception ex)
   at Microsoft.Owin.Host.SystemWeb.CallContextAsyncResult.End(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)



Request information: 
    Request URL: http://example.com:port/signalr/abort?transport=serverSentEvents&connectionToken=0D8V3TwV78z1cU7_kbQGaSjZH1r_w4eGkkFPRftDiZXPJjbEZmXEluSOkvzVBDRQOGWzVPGfeCKdsvEUwhzb07-Kph-pJ3oog_ydjvsRSnoXqDnYZkPXwJgPrFsFYtmpFDKe0hOvHS7ZxApQF_4fbw2 
    Request path: /signalr/abort 
    User host address: A.B.C.D 
    User:  
    Is authenticated: False 
    Authentication Type:  
    Thread account name: IIS APPPOOL\DefaultAppPool 

Thread information: 
    Thread ID: 63 
    Thread account name: IIS APPPOOL\DefaultAppPool 
    Is impersonating: False 
    Stack trace:    at Microsoft.Owin.Host.SystemWeb.Utils.<>c__DisplayClass1.<GetRethrowWithNoStackLossDelegate>b__0(Exception ex)
   at Microsoft.Owin.Host.SystemWeb.CallContextAsyncResult.End(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

【问题讨论】:

  • 你使用 Redis / SQL Server scaleout 吗?
  • @MosheL 不,我没有。从未真正听说过这些。

标签: asp.net asp.net-mvc asp.net-mvc-4 signalr


【解决方案1】:

只是“大声思考”,如果问题只是因为会话过期,您可能想尝试在服务器上的会话结束时拦截并向所有受影响的客户端广播消息(为此添加逻辑) 要求他们明确断开连接并避免他们破坏您的服务器。我猜您的会话与身份验证相关联,因此无论如何都必须进行登录,因此您将在此之后重新连接 SignalR。说得通?

您还可以让客户端超时在 N-1 分钟后到期,其中 N 是会话的持续时间。并让那个强制断开连接。如果服务器上发生的事情使时间窗口移动,则可以使用 SignalR 本身更新超时本身。

两者都是实用、快速和肮脏的解决方案,将 SignalR 和 Session 保持在一起。

【讨论】:

  • 会话会丢失从而导致n-1 方法失败吗?会话结束时如何拦截?没有任何事件被触发(至少我不知道),会话结束的真正影响是用户向服务器发出某种请求时。
  • 服务器端,你有一个很好的旧 Session_End 事件,这可能会有所帮助。在该事件中,您可以通知相关客户并要求断开连接。在任何其他情况下,我们可以假设会话处于活动状态,因此 thr N-1 策略应该有效。当然,您必须为您可能在 SignalR 之外执行的任何异步请求重置客户端超时。正如我所说,这是一个想法,我从来没有遇到过这个问题,我不能 100% 确定它会起作用,但它看起来有一些探索的潜力。
【解决方案2】:

您可以在thread 中找到一个很好的解释。看来您不能以某种方式将 Session 与 SignalR 一起使用。 希望对你有帮助。

【讨论】:

  • 谢谢。自从您的回复以来,我一直在阅读许多有关禁用 Session 的文章。很有意思。如果有任何进展,我会看看进展如何并更新。
【解决方案3】:

【讨论】:

  • 我不认为第一个链接是问题的解决方案,它只是在标题中有一个名称“会话”。或者也许我错了?第二个也没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
相关资源
最近更新 更多