在 .NET 依赖项注入中,gRPC 通道应该是单例的、范围的还是瞬态的?

问题描述

.NET 中的 gRPC 请求依赖于必须关闭和处理的通道:

using var channel = Grpc.Net.Client.GrpcChannel.ForAddress("path to service");

//...do stuff...

await channel.ShutdownAsync();

我正在使用 IServiceCollection 将其包装在 .NET 依赖项注入服务中,这应该是...

  • 方法 - 在每个方法调用中创建和处理通道。
  • AddTransient - 每次请求我的服务时都会创建一个新频道,但仅限于需要时。
  • AddScoped - 为每个请求创建一个新通道,但在请求完成之前保持通道打开。
  • AddSingleton - 应用的单一新渠道。

认为 AddSingleton 已出局,因为我不确定 GrpcChannel 将如何同时处理大量并行请求,我想通过CancellationToken 用于当前请求。

AddScopedAddTransient 与按方法之间进行选择。没有大量的测试(并跌跌撞撞地陷入所有陷阱)我不确定这里的最佳实践是什么(我是 gRPC 的新手)。我应该尽快关闭频道,还是保持打开状态并在通话之间共享它?

解决方法

据微软称 https://docs.microsoft.com/en-us/aspnet/core/grpc/client?view=aspnetcore-5.0#client-performance

通道代表与 gRPC 服务的长期连接。

渠道和客户的表现和使用情况:

  • 创建频道可能是一项代价高昂的操作。为 gRPC 调用重用通道可提供性能优势。
  • gRPC 客户端是通过通道创建的。 gRPC 客户端是轻量级对象,不需要缓存或重用。
  • 可以从一个通道创建多个 gRPC 客户端,包括不同类型的客户端。
  • 一个通道和从该通道创建的客户端可以安全地被多个线程使用。
  • 从频道创建的客户端可以同时进行多个呼叫。需要缓存或重用。多个 gRPC 客户端可以 从频道创建,包括不同类型的客户端。一种 通道和从通道创建的客户端可以安全地使用 多线程。从频道创建的客户端可以使 多个同时调用。

根据 grpc https://grpc.github.io/grpc/csharp-dotnet/api/Grpc.Net.Client.GrpcChannel.html :

Class GrpcChannel 代表一个 gRPC 通道。渠道是一个 到远程服务器的长期连接的抽象。客户 对象可以重用相同的通道。创建频道的成本很高 操作与调用远程调用相比,所以一般来说你应该 为尽可能多的调用重用单个通道。

与往常一样,这取决于您要做什么,但单例可能只应创建单个通道。此外,如果您确实需要处理繁重的负载,请尝试使用 SocketsHttpHandler.EnableMultipleHttp2Connections (https://docs.microsoft.com/en-us/aspnet/core/grpc/performance?view=aspnetcore-5.0#connection-concurrency)