问题描述
我正在为我的应用程序设置分布式跟踪。应用程序中的连接之一是使用 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
解决方法
记录和跟踪实际上是相同技术的两个名称。
- 您可以使用日志系统来收集诊断信息以帮助解决问题。
- Logging and diagnostics in ASP.NET Core SignalR
- .NET Core logging and tracing
如果要实施分布式跟踪,可以为 ASP.NET Core 应用程序启用 Application Insights。
,经过大量研究,SignalR 不仅在消息调用生命周期几乎没有或没有可扩展性选项(唯一可用的似乎是 HubFilters),而且它根本不支持 W3C 跟踪上下文。我已经自己实现了这一点,但这是一项艰巨的任务,所以我正在推迟查看 MS 是否会在接下来的 8 到 12 个月内开始支持它。这是希望。
更多关于我对如何手动实现这一点的思考......
集线器过滤器
这些仅在消息来自连接的客户端之一时提供可扩展性接触点。在客户端请求的方法调用发生之前,您有机会检查来自客户端的消息,并可以对中心位置的所有消息采取行动。对于发送到客户端、由客户端接收或从客户端发送的消息,似乎没有此类可扩展性选项。为了在这些点注入代码,您必须通过将所有函数调用包装在另一个函数中来手动执行。
标题和查询字符串支持
SignalR 确实允许您向查询字符串添加标头和数据,但由于 Websocket 通信不是通过 HTTP 协议进行的,因此无法使用这些标头传递特定于每条消息的数据。
结论
如果您想支持从带有 websockets 的 SignalR 中的 W3C 跟踪上下文实现中获得的相同功能,您需要在与客户端或服务器之间的每个请求中传递一个公共对象(我称之为我的 SignalRContext)。此对象可用于至少传递一个 TraceId 以帮助将所有应用程序跟踪联系在一起。