ASP.Net Core SignalR 是否支持 W3C 跟踪上下文或任何类型的分布式跟踪?

问题描述

我正在为我的应用程序设置分布式跟踪。应用程序中的连接之一是使用 SignalR 的 WebSocket 连接。 SignalR连接的两端都是asp.net核心应用。一个是 Windows 服务(客户端),另一个在 Web 服务器(服务器)下运行。

通信将来自两个方向,因此我将使用来自连接两端的请求的 TraceIds。 SignalR 是否具有来回传递此跟踪信息的功能?我到处搜索,几乎没有关于 SignalR 支持 W3C 跟踪上下文的信息,甚至没有像 .net core pre 2.0 这样的自定义实现的跟踪系统。

在服务器端发出请求时,我尝试创建一个新的 Activity,但我认为没有任何跟踪信息将其发送到客户端。我可能没有找对地方,但是当我在客户端上检查 System.Diagnostics.Activity.CurrentActivity 时,我只得到 null,即使在我拨打电话时在服务器上有以下活动。>

System.Diagnostics.Activity.Current
{System.Diagnostics.Activity}
    ActivityTraceFlags: None
    Baggage: {System.Collections.Generic.keyvaluePair<string,string>[0]}
    Context: {System.Diagnostics.ActivityContext}
    displayName: "Microsoft.AspNetCore.Hosting.HttpRequestIn"
    Duration: {00:00:00}
    Events: {System.Diagnostics.ActivityEvent[0]}
    Id: "00-eb7a4125a171a6438a44ddda5a637cd0-f7c16b0bb8512443-00"
    IdFormat: W3C
    IsAllDataRequested: true
    Kind: Internal
    Links: {System.Diagnostics.ActivityLink[0]}
    OperationName: "Microsoft.AspNetCore.Hosting.HttpRequestIn"
    Parent: null
    ParentId: null
    ParentSpanId: {0000000000000000}
    Recorded: false
    RootId: "eb7a4125a171a6438a44ddda5a637cd0"
    Source: {System.Diagnostics.ActivitySource}
    SpanId: {f7c16b0bb8512443}
    StartTimeUtc: {7/13/2021 11:26:13 PM}
    TagObjects: {System.Collections.Generic.keyvaluePair<string,object>[0]}
    Tags: {System.Collections.Generic.keyvaluePair<string,string>[0]}
    TraceId: {eb7a4125a171a6438a44ddda5a637cd0}
    TraceStateString: null

我希望有人能对此有所了解。

谢谢!

-=-=-=-= 编辑 -=-=-=-=

当托管在 Blazor 应用程序中时,SignalR 似乎至少支持某种级别的 W3C 上下文跟踪。不知道该怎么做。 https://github.com/dotnet/aspnetcore/issues/29846

解决方法

记录跟踪实际上是相同技术的两个名称。

  1. 您可以使用日志系统来收集诊断信息以帮助解决问题。
  2. Logging and diagnostics in ASP.NET Core SignalR
  3. .NET Core logging and tracing

如果要实施分布式跟踪,可以为 ASP.NET Core 应用程序启用 Application Insights

  1. Application Insights for ASP.NET Core applications
  2. .NET distributed tracing
,

经过大量研究,SignalR 不仅在消息调用生命周期几乎没有或没有可扩展性选项(唯一可用的似乎是 HubFilters),而且它根本不支持 W3C 跟踪上下文。我已经自己实现了这一点,但这是一项艰巨的任务,所以我正在推迟查看 MS 是否会在接下来的 8 到 12 个月内开始支持它。这是希望。

更多关于我对如何手动实现这一点的思考......

集线器过滤器

这些仅在消息来自连接的客户端之一时提供可扩展性接触点。在客户端请求的方法调用发生之前,您有机会检查来自客户端的消息,并可以对中心位置的所有消息采取行动。对于发送到客户端、由客户端接收或从客户端发送的消息,似乎没有此类可扩展性选项。为了在这些点注入代码,您必须通过将所有函数调用包装在另一个函数中来手动执行。

标题和查询字符串支持

SignalR 确实允许您向查询字符串添加标头和数据,但由于 Websocket 通信不是通过 HTTP 协议进行的,因此无法使用这些标头传递特定于每条消息的数据。

结论

如果您想支持从带有 websockets 的 SignalR 中的 W3C 跟踪上下文实现中获得的相同功能,您需要在与客户端或服务器之间的每个请求中传递一个公共对象(我称之为我的 SignalRContext)。此对象可用于至少传递一个 TraceId 以帮助将所有应用程序跟踪联系在一起。