Komunikace mezi procesy pomocí služby gRPC

Od James Newton – král

gRPC volání mezi klientem a službou se obvykle odesílají přes sokety TCP. Protokol TCP byl navržen pro komunikaci přes síť. Komunikace mezi procesy (IPC) je efektivnější než TCP, pokud je klient a služba ve stejném počítači. Tento dokument vysvětluje, jak používat gRPC s vlastními přenosy ve scénářích IPC.

Konfigurace serveru

Vlastní přenosová podpora je podporována nástrojem Kestrel . Kestrel je nakonfigurovaný v programu 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, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                });
            });
        });

Předchozí příklad:

Kestrel má vestavěnou podporu pro koncové body UDS. Verze UDS je podporovaná v systémech Linux, macOS a moderních verzích Windows.

Konfigurace klienta

GrpcChannel podporuje vytváření volání gRPC pomocí vlastních přenosů. Při vytvoření kanálu je možné ho nakonfigurovat s SocketsHttpHandler vlastním ConnectCallback . Zpětné volání umožňuje klientovi vytvořit připojení přes vlastní přenosy a pak odesílat požadavky HTTP prostřednictvím tohoto přenosu.

Příklad vytváření připojení k doménovým soketům UNIX:

public class UnixDomainSocketConnectionFactory
{
    private readonly EndPoint _endPoint;

    public UnixDomainSocketConnectionFactory(EndPoint endPoint)
    {
        _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(_endPoint, cancellationToken).ConfigureAwait(false);
            return new NetworkStream(socket, true);
        }
        catch
        {
            socket.Dispose();
            throw;
        }
    }
}

Vytvoření kanálu pomocí vlastního objektu pro vytváření připojení:

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

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

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

Kanály vytvořené pomocí předchozího kódu odesílají gRPC volání prostřednictvím doménových soketů systému UNIX. Podporu jiných technologií IPC lze implementovat pomocí rozšíření v Kestrel a SocketsHttpHandler .