Net Core gRPC - 08. 客户端工厂集成与进程间通信
Net Core gRPC 系列
 1. 什么是客户端工厂集成
gRPC 与 HttpClientFactory 的集成提供了一种创建 gRPC 客户端的集中方式。 它可用作配置独立 gRPC 客户端实例的替代方法。 Grpc.Net.ClientFactory NuGet 包中提供了工厂集成。
工厂具有以下优势:
提供了用于配置逻辑 gRPC 客户端实例的中心位置
可管理基础 HttpClientMessageHandler 的生存期
在 ASP.NET Core gRPC 服务中自动传播截止时间和取消
1 2 3 4
   | services.AddGrpcClient<Greeter.GreeterClient>(o => {     o.Address = new Uri("https://localhost:5001"); });
   | 
 2. 进程间通信
不同计算机上的客户端和服务器之间的 gRPC 调用通常通过 TCP 套接字发送。 TCP 是跨网络或 Internet 进行通信的绝佳选择。 但是,当客户端和服务器位于同一台计算机上时,IPC 传输可以提供性能优势,更好地与 OS 功能集成。
.NET 支持多个 IPC 传输:
Unix 域套接字 (UDS) 是一种广泛受支持的 IPC 技术。 UDS 是生成跨平台应用的最佳选择,可在 Linux、macOS 和 Windows 10/Windows Server 2019 或更高版本上使用。
所有版本的 Windows 都支持命名管道。 命名管道与 Windows 安全性良好集成,可用于控制客户端对管道的访问。
通过在应用启动时实现 IConnectionListenerFactory 和注册实现进行的其他 IPC 传输。
 ❗ 备注
ASP.NET Core 中对命名管道的内置支持需要 .NET 8 或更高版本。 .NET 8 目前为预览版,将于 2023 年底发布。
Unix进程间通信1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | public class UnixDomainSocketsConnectionFactory {     private readonly EndPoint endPoint;
      public UnixDomainSocketsConnectionFactory(EndPoint endPoint)     {         this.endPoint = endPoint;     }
      public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,         CancellationToken cancellationToken = default)     {         var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
          try         {             await socket.ConnectAsync(this.endPoint, cancellationToken).ConfigureAwait(false);             return new NetworkStream(socket, true);         }         catch         {             socket.Dispose();             throw;         }     } }
   | 
 windows 进程间通信1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   | 
 
  public class NamedPipesConnectionFactory {     private readonly string _pipeName;
      public NamedPipesConnectionFactory(string pipeName)     {         _pipeName = pipeName;     }
      public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,         CancellationToken cancellationToken = default)     {         var clientStream = new NamedPipeClientStream(             serverName: ".",             pipeName: _pipeName,             direction: PipeDirection.InOut,             options: PipeOptions.WriteThrough | PipeOptions.Asynchronous,             impersonationLevel: TokenImpersonationLevel.Anonymous);         try         {             await clientStream.ConnectAsync(cancellationToken).ConfigureAwait(false);             return clientStream;         }         catch         {             clientStream.Dispose();             throw;         }     } }
 
  | 
  3. 使用策略模式创建Grpc channel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   | public interface IColaGrpc {     GrpcChannel CreateChannel(string grpcUrl, string? pipeNameOrSocketPath=null); }
  public class ColaWindowsGrpc : IColaGrpc {     public GrpcChannel CreateChannel(string grpcUrl, string? pipeNameOrSocketPath=null)     {     	                             if (SystemHelper.NetCoreVersion!.Major > 8)         {             var connectionFactory = new NamedPipesConnectionFactory(pipeNameOrSocketPath!);             var socketsHttpHandler = new SocketsHttpHandler             {                 ConnectCallback = connectionFactory.ConnectAsync             };             return GrpcChannel.ForAddress(grpcUrl, new GrpcChannelOptions             {                 HttpHandler = socketsHttpHandler             });         }         return GrpcChannel.ForAddress(grpcUrl);     } } public class ColaUnixGrpc : IColaGrpc {     public GrpcChannel CreateChannel(string grpcUrl, string? pipeNameOrSocketPath=null)     {         var udsEndPoint = new UnixDomainSocketEndPoint(pipeNameOrSocketPath!);         var connectionFactory = new UnixDomainSocketsConnectionFactory(udsEndPoint);         var socketsHttpHandler = new SocketsHttpHandler         {             ConnectCallback = connectionFactory.ConnectAsync         };         return GrpcChannel.ForAddress(grpcUrl, new GrpcChannelOptions         {             HttpHandler = socketsHttpHandler         });     } } public class ColaGrpcHelper {     private readonly IColaGrpc _colaGrpc;          public ColaGrpcHelper(IColaGrpc colaGrpc)     {         _colaGrpc = colaGrpc;     }          public GrpcChannel CreateChannel(string grpcUrl, string? pipeNameOrSocketPath=null)     {         return _colaGrpc.CreateChannel(grpcUrl, pipeNameOrSocketPath);     } }
   | 
创建channel
1
   | var channel = new ColaGrpcHelper(new ColaWindowsGrpc()).CreateChannel("https://localhost:5005");
  | 
完整代码可以在 GitHub
WebApplication1Test 整合了gRPC,ConsoleApp1Test有具体调用示例