首页 > 解决方案 > ASP.Net Core SignalR 是否支持 W3C 跟踪上下文或任何类型的分布式跟踪?

问题描述

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

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

在服务器端发出请求时,我尝试创建一个新的活动,但我认为没有任何跟踪信息正在发送给客户端。我可能没有找对地方,但是当我检查客户端时,即使在服务器上我在拨打电话时有以下活动,我也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

标签: asp.net-coresignalrasp.net-core-5.0distributed-tracing

解决方案


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

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

集线器过滤器

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

标头和查询字符串支持

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

结论

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


推荐阅读