AspNetCore.Docs/aspnetcore/grpc/interprocess.md

3.6 KiB

title author description monikerRange ms.author ms.date no-loc uid
Inter-process communication with gRPC jamesnk Learn how to use gRPC for inter-process communication. >= aspnetcore-5.0 jamesnk 08/24/2020
ASP.NET Core Identity
cookie
Cookie
Blazor
Blazor Server
Blazor WebAssembly
Identity
Let's Encrypt
Razor
SignalR
grpc/interprocess

Inter-process communication with gRPC

By James Newton-King

gRPC calls between a client and service are usually sent over TCP sockets. TCP is great for communicating across a network, but inter-process communication (IPC) is more efficient when the client and service are on the same machine. This document explains how to use gRPC with custom transports in IPC scenarios.

Server configuration

Custom transports are supported by Kestrel. Kestrel is configured in Program.cs:

public static readonly string SocketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
            webBuilder.ConfigureKestrel(options =>
            {
                if (File.Exists(SocketPath))
                {
                    File.Delete(SocketPath);
                }
                options.ListenUnixSocket(SocketPath);
            });
        });

The preceding example:

Kestrel has built-in support for UDS endpoints. UDS are supported on Linux, macOS and modern versions of Windows.

Client configuration

GrpcChannel supports making gRPC calls over custom transports. When a channel is created, it can be configured with a SocketsHttpHandler that has a custom ConnectionFactory. The factory allows the client to make connections over custom transports and then send HTTP requests over that transport.

[!IMPORTANT] ConnectionFactory is a new API in .NET 5 release candidate 1.

Unix domain sockets connection factory example:

public class UnixDomainSocketConnectionFactory : SocketsConnectionFactory
{
    private readonly EndPoint _endPoint;

    public UnixDomainSocketConnectionFactory(EndPoint endPoint)
        : base(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)
    {
        _endPoint = endPoint;
    }

    public override ValueTask<Connection> ConnectAsync(EndPoint? endPoint,
        IConnectionProperties? options = null, CancellationToken cancellationToken = default)
    {
        return base.ConnectAsync(_endPoint, options, cancellationToken);
    }
}

Using the custom connection factory to create a channel:

public static readonly string SocketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");

public static GrpcChannel CreateChannel()
{
    var udsEndPoint = new UnixDomainSocketEndPoint(SocketPath);
    var socketsHttpHandler = new SocketsHttpHandler
    {
        ConnectionFactory = new UnixDomainSocketConnectionFactory(udsEndPoint)
    };

    return GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
    {
        HttpHandler = socketsHttpHandler
    });
}

Channels created using the preceding code send gRPC calls over Unix domain sockets.