对中转服务进行故障排除
适用于: Visual Studio 2019 及更高版本
本文介绍在 Visual Studio SDK 中尝试获取 中转服务 时可能出现的几个常见问题的故障排除建议和可能的解决方案。
中转服务可能以各种方式失败。 启动调查的一种有用技术是检查 Visual Studio 活动日志,该日志通常会记录错误或警告,当事务与中转服务发生争吵时, 这些日志通常会记录错误或警告。
请求服务时出现的问题
也许中转服务最常见的挑战是了解从调用或IServiceBroker.GetPipeAsync获取IServiceBroker.GetProxyAsync的结果或异常。 有意 IServiceBroker 将有关代理服务激活位置和方式的担忧抽象化。 但是,当出现问题时,有必要更深入地诊断和纠正问题。
无服务
服务请求的结果可能是 null
满足以下任一条件:
- 未注册请求的服务。 中转服务作者应将其注册到 ProvideBrokeredServiceAttribute 或手动创作 的 .pkgdef 文件。
- 请求的服务注册到未向此客户端公开服务的配置。 默认范围是 ServiceAudience.Process,这意味着仅当从客户端的同一进程中调用中转服务时,才能激活中转服务。 如果客户端处于另一个进程中,并且该意向是让中转服务可供其使用,请更改服务注册以将其扩展 ServiceAudience。
- 请求的服务注册到 ServiceAudience.LiveShareGuest,存在 Live Share 连接,但主机不提供中转服务或 ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients 属性未设置为
true
。 通过 Live Share 公开中转服务时,请查看 如何保护中转服务。 - 请求的服务已注册,但缺少有关要初始化的包的信息,以便可以教授其工厂。 该 ProvideBrokeredServiceAttribute 属性自动生成注册,该注册指示应用了该属性的包,以便 Visual Studio 可以根据需要加载该包。 如果属性应用于错误的包或 手动创作 .pkgdef 文件,则此信息可能缺失或不准确。
- 负责在初始化期间引发中转服务或否则无法实际教授该服务工厂的 Visual Studio 包。 检查 Visual Studio 活动日志 ,了解包加载失败的证据。
- 服务工厂本身返回
null
。
服务请求引发异常
当服务工厂引发异常时,服务请求可能会引发 ServiceCompositionException 。 这意味着上面列出的所有问题都会导致 null
结果不适用。 查看异常详细信息(包括内部异常),了解出错的情况,并对任何客户端或服务工厂进行必要的更正。
在预期远程服务时,你会收到本地服务
请求可能在本地或远程完成,具体取决于服务注册和 Visual Studio 的当前状态。 默认范围是 ServiceAudience.Process,这意味着仅当从客户端的同一进程中调用中转服务时,才能激活中转服务。
如果应将中转服务从 Live Share 主机公开到连接的来宾,但 ServiceAudience 仅限于本地范围,来自 Live Share 来宾的请求将从同一台计算机而不是主机激活中转服务。 更新注册以包括 ServiceAudience.LiveShareGuest 通过 Live Share 公开中转服务。 可能还需要设置 ProvideBrokeredServiceAttribute.AllowTransitiveGuestClients 到该设置 true
。
提供服务时出现的问题
除非通过 MEF 导出中转服务,否则必须从AsyncPackage类中提供中转服务,如如何提供中转服务中所述。
如果满足以下任一条件,则尝试提供中转服务将引发异常:
- 所提供服务的名字对象与已注册的服务不完全匹配(名称和版本)。
- 已为同一服务名字对象提供工厂。
调用 IBrokeredServiceContainer.Proffer 的结果是一个 IDisposable。 释放此值后,中转服务对新请求不可用。 如果中转服务具有与某些上下文(如开放解决方案)的特定关联,则仅当该上下文处于活动状态时,才适合提供中转服务。 释放包时,无需保留和释放此值。
跟踪客户端和服务之间的 RPC
建立客户端和服务之间的连接后,跟踪其通信可能会很有用,尤其是在不同进程中时。
默认情况下,跨进程(例如 RPC 应用)的中转服务之间的通信跟踪记录在目录中的 %TEMP%\VSLogs
.svclog 文件中。 这些 xml 文件最好与服务跟踪查看器一起查看。 此工具可以同时打开许多 .svclog 文件,并将它们拼凑在一起,形成多方图,以便更轻松地了解客户端和服务之间的 RPC。
中转服务本身可以直接跟踪以添加到这些 .svclog 跟踪文件,从而进一步帮助诊断中转服务行为。 调用“报告问题”命令并用户选择共享日志时,可能会收集保存到 %TEMP%\VSLogs
的任何跟踪。
若要跟踪自己的消息,以便可以轻松发现它们并将其与其他 .svclog 跟踪相结合,代码(无论是中转服务)可以执行如下所示的内容:
// Define your log's ID, a namespace-like fully qualified name.
// In general it is expected that you follow you team's assembly namespace.
// Also an optional parameter, the ServiceMoniker for your service
var myLogId = new LogId("Microsoft.SomeTeam.MyLogName", serviceId: null);
var requestedLevel = new LoggingLevelSettings(SourceLevels.Warning | SourceLevels.ActivityTracing);
var myLogOptions = new LoggerOptions(requestedLevel, PrivacyFlags.MayContainPrivateInformation);
TraceSource myTraceSource;
using (TraceConfiguration traceConfig = await TraceConfiguration.CreateTraceConfigurationInstanceAsync(serviceBroker, ownsServiceBroker: false, cancellationToken))
{
myTraceSource = await traceConfig.RegisterLogSourceAsync(myLogId, myLogOptions, traceSource: null, cancellationToken);
}
myTraceSource
现在可用于跟踪,因为它添加了相应的侦听器,用于将跟踪写入 .svclog 文件。 如果已有一个 TraceSource 想要使用的方法,请将其 RegisterLogSourceAsync 传递给该方法,并放弃结果,因为侦听器将添加到现有 TraceSource侦听器。
从为远程客户端提供服务的中转服务进行跟踪时,会自动将活动分配给 ExecutionContext 代码在其中运行的活动,以便将 svclog 与客户端的 svclog 拼凑在一起,以便使用 服务跟踪查看器查看整体视图。