Freigeben über


Prozessübergreifende Kommunikation mit gRPC- und Unix-Domänensockets

Von James Newton-King

.NET unterstützt die prozessübergreifende Kommunikation (Inter-Process Communication, IPC) mithilfe von gRPC. Weitere Informationen zu den ersten Schritten mit der Verwendung von gRPC für die Kommunikation zwischen Prozessen finden Sie unter Inter-Process Communication mit gRPC.

Unix-Domänensockets (UDS) sind ein breit unterstützter IPC-Transport, der effizienter ist als TCP, wenn sich der Client und der Server auf demselben Computer befinden. In diesem Artikel wird erläutert, wie Sie die gRPC-Kommunikation über UDS konfigurieren.

Voraussetzungen

Serverkonfiguration

Unix-Domänensockets werden von Kestrel unterstützt. Die Konfiguration erfolgt in Program.cs:

var socketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenUnixSocket(socketPath, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http2;
    });
});

Für das vorherige Beispiel gilt Folgendes:

Clientkonfiguration

GrpcChannel unterstützt gRPC-Aufrufe für benutzerdefinierte Datentransporte. Wenn ein Kanal erstellt wird, kann er mit einer SocketsHttpHandler-Klasse konfiguriert werden, die über ein benutzerdefiniertes ConnectCallback-Objekt verfügt. Der Rückruf ermöglicht es dem Client, Verbindungen für benutzerdefinierte Datentransporte herzustellen und dann HTTP-Anforderungen über diese Datentransporte zu senden.

Hinweis

Einige Konnektivitätsfeatures von GrpcChannel, z. B. clientseitiger Lastenausgleich und Kanalstatus, können nicht zusammen mit Unix-Domänensockets verwendet werden.

Beispiel für eine UDS-Verbindungsfactory (Unix Domain Socket):

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;
        }
    }
}

So wird die benutzerdefinierte Verbindungsfactory zum Erstellen eines Kanals verwendet:

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

public static GrpcChannel CreateChannel()
{
    var udsEndPoint = new UnixDomainSocketEndPoint(SocketPath);
    var connectionFactory = new UnixDomainSocketsConnectionFactory(udsEndPoint);
    var socketsHttpHandler = new SocketsHttpHandler
    {
        ConnectCallback = connectionFactory.ConnectAsync
    };

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

Kanäle, die mithilfe des vorangehenden Codes erstellt werden, senden gRPC-Aufrufe über Unix Domain Sockets (UDS).