【问题标题】:Getting SignalR connection startup error stack获取 SignalR 连接启动错误堆栈
【发布时间】:2020-03-03 23:02:26
【问题描述】:

在 SignalR 连接设置期间,如何获取在其他正常运行的 Web 应用程序中发生的异常的完整堆栈?

背景

我是维护一个带有 C# 客户端的 Web 应用程序的团队的一员,该应用程序使用极其基本的 SignalR 设置(2.2 版)在长时间运行的服务器进程期间有效地提供有关进度的推送通知。比如,开箱即用,

app.MapSignalR();
HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");
await connection.Start();

基本的。我们的一些客户端在远程服务上运行,并定期遇到 Web 应用程序的其他功能正常工作的问题,但调用 connection.Start() 的客户端代码返回 500 内部服务器错误,没有更多信息。他们可以通过刷新远程连接来解决这个问题,但这并不理想,所以我试图获取一些关于连接设置过程中发生此错误的位置的信息。

问题

Following the information about setting up error handling for SignalR on MSDN,我尝试通过将以下管道模块插入GlobalHost.HubPipeline 来模拟问题:

public class HubErrorHandlingModule : HubPipelineModule
  {
    public override Func<IHub, Task> BuildConnect(Func<IHub, Task> connect)
    {
      throw new InvalidOperationException("Testing Connection Exceptions");
    }

    protected override void OnIncomingError(ExceptionContext exceptionContext, 
      IHubIncomingInvokerContext invokerContext)
    {
      // some logging happens here
      base.OnIncomingError(exceptionContext, invokerContext);
    }
  }

它确实有效,因为我可以看到管道代码中抛出了异常,并且我的测试 C# 客户端也看到了 500 内部服务器错误,没有更多信息。

但它也有点不起作用,因为我已经在断点中删除并且 OnIncomingError 代码永远不会被命中。这是有道理的,因为它不是导致异常的任何 Hub 方法中的代码,但我不知道这个异常发生在哪里;它可以在客户调用connection.Start期间的任何地方。

我也尝试过用EnableDetailedErrors = true 传递一个备用​​HubConfiguration,但这似乎没有任何改善。

从哪里获得完整的堆栈跟踪并不重要,因为我同时控制服务器和客户端代码,但为了了解他们的问题,我需要查看完整的跟踪某处 .

我尝试了什么以及为什么它不起作用

app.MapSignalR(new HubConfiguration { EnableDetailedErrors = true });

我认为这是为了显示来自Hub 处理的详细错误,而不是连接握手?据说它的目的是发送一条标记为错误的消息,即使它从未冒泡给任何消费者,也可能被连接跟踪。可惜……

var writer = new StreamWriter("C:\\Logs\\ClientLog.txt");
writer.AutoFlush = true;
connection.TraceLevel = TraceLevels.All;
connection.TraceWriter = writer;

一旦我消除了故意的管道错误,这确实会跟踪到 SignalR 后端的成功通信。但是当我重新设置它时,我看到的只是建立连接的失败尝试和 500 内部服务器错误。没有痕迹。

<system.diagnostics>
  <sharedListeners ... >
  <switches ...>
  <sources ...>
  <trace autoflush="true" />
</system.diagnostics>

the MSDN trace detailsthis commentary on GitHub 之后设置。这两组细节都不起作用。当我通过将管道异常移动到不同的管道事件来进行游戏时,有时我可以看到堆栈跟踪出现在 SignalR.HubDispatcher 源中,仅在 GitHub 详细信息中提到,但是当我在建立连接后抛出异常时会发生这种情况并且到达客户端的是一个不同于 500 内部服务器错误的错误,因此这可能发生得太晚了,无法成为客户端安装的任何问题。

【问题讨论】:

  • 嘿 Glazius,如果您需要更多帮助或对解决方案有任何疑问,请随时发表评论
  • 我想我以前遇到过这个问题。很确定问题来自这里HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");。您需要将 SignalR.cs 放在项目的根路径中。至少这对我来说是个问题。

标签: c# asp.net-mvc-4 signalr.client signalr-2


【解决方案1】:

就我而言,我必须将 SignalR.cs 放在我的根路径中

然后在视图中我包含脚本:

<script src="~/signalr/hubs"></script>

这就是我的 SignalR.cs 的样子:

public class NotificationHub : Hub
{
    public void SendUpdateNotification(string message)
    {
        // message = "show" / "hide"
        if (message.Equals("show"))
            Config._MaintenanceMode = true;
        else
            Config._MaintenanceMode = false;

        // Call the broadcastUpdate method to update clients.
        Clients.All.broadcastUpdate(message);
    }
}

【讨论】:

  • 我不明白这与任何事情有什么关系。我使用的是 C# 客户端,而不是 Web 客户端 - 该应用程序提供主要包含 JSON 的 HTTP 响应。它的 SignalR 部分也在开发服务器上始终如一地工作,并且只是在现场间歇性地失败。我不明白这如何帮助我在 connection.Start() 失败时记录堆栈跟踪。
  • 可能HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");这里的url不对,或者服务器不允许CORS连接。
  • 集线器类名是signalr吗?尝试将“/signalr”更改为“/hubName”
  • 我真的不明白你在说什么。我正在使用 SignalR 2 - 你是在谈论不同的版本吗?我有多个类型的集线器,它们都通过 app.mapSignalR() 链接到公共端点,并通过客户端上的 CreateHubProxy 进行监控。网址正确;它可以在我们的开发环境和大多数安装中运行。它只是间歇性地失败,我想要的只是一个堆栈跟踪,以便更好地了解原因。
【解决方案2】:

要处理 SignalR 引发的错误,您可以为连接对象上的错误事件添加处理程序

connection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.StackTrace);

要处理来自方法调用的错误,请将代码包装在 try-catch 块中。

HubConnection connection = new HubConnection(_applicationConfiguration.ApiBaseUri + "/signalr");
try
{   
    await connection.Start(); 
}
catch (Exception ex)
{
    Console.WriteLine("Error " + ex);
}

要启用详细的错误消息以进行故障排除,

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
App.MapSignalR(hubConfiguration);

在您的代码中,集线器管道模块我没有看到您正在记录/打印错误

Console.WriteLine("Exception " + exceptionContext.Error.Message);
base.OnIncomingError(exceptionContext, invokerContext);

现在连接我们创建的自定义 HubPipelineModule,这是在启动类中实现的

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        GlobalHost.HubPipeline.AddModule(new HubErrorHandlingModule());

        app.MapSignalR();
    }
}

参考文献:

SignalR Notify user about disconnections
SingalR How to Handle Errors
SignalR 500 Internal Server Error

【讨论】:

  • 在这个例子中,我会在哪里看到 HubErrorHandlingModule 抛出的 InvalidOperationException?
  • 您订阅了示例中的事件处理程序 connection.Error+= 还是将您的 connection.Start() 包围在 try-catch 中?
  • connection.Error 没有被触发。这是有道理的; Web 应用程序功能正常,在现场人们必须连接到它以组装启动点以进行长时间操作,从而建立 SignalR 连接。从 connection.Start() 中捕获了一个非聚合异常。它的堆栈跟踪在 connection.Start() 处结束。我看不到 HubErrorHandlingModule 抛出的 InvalidOperationException。
  • 是的,对于 Exception ex 而不是仅打印堆栈跟踪,您是否尝试打印整个对象,例如 Console.WriteLine("Error " + ex);
猜你喜欢
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2023-03-24
  • 2021-10-23
  • 2022-11-07
  • 1970-01-01
相关资源
最近更新 更多