Condividi tramite


Comunicazione tra processi con socket di dominio gRPC e Unix

Di James Newton-King

.NET supporta la comunicazione tra processi (IPC) tramite gRPC. Per altre informazioni sull'uso di gRPC per comunicare tra processi, vedere Comunicazione tra processi con gRPC.

I socket di dominio Unix (UDS) sono un trasporto IPC ampiamente supportato che è più efficiente di TCP quando il client e il server si trovano nello stesso computer. Questo articolo illustra come configurare la comunicazione gRPC tramite UDS.

Prerequisiti

Configurazione del server

I socket di dominio Unix sono supportati da Kestrel, che è configurato 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;
    });
});

L'esempio precedente:

Configurazione del client

GrpcChannel supporta l'esecuzione di chiamate gRPC su trasporti personalizzati. Quando viene creato un canale, può essere configurato con un SocketsHttpHandler oggetto con un oggetto personalizzato ConnectCallback. Il callback consente al client di effettuare connessioni su trasporti personalizzati e quindi inviare richieste HTTP su tale trasporto.

Nota

Alcune funzionalità di connettività di GrpcChannel, ad esempio il bilanciamento del carico lato client e lo stato del canale, non possono essere usate insieme ai socket di dominio Unix.

Esempio di factory di connessione socket di dominio Unix:

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

Uso della factory di connessione personalizzata per creare un canale:

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

Canali creati usando il codice precedente inviano chiamate gRPC su socket di dominio Unix.