Взаимодействие между процессами с gRPC и именованными каналами

Автор: Джеймс Ньютон-Кинг (James Newton-King)

.NET поддерживает взаимодействие между процессами (IPC) с помощью gRPC. Дополнительные сведения о начале работы с использованием gRPC для обмена данными между процессами см. в разделе "Взаимодействие между процессами" с gRPC.

Именованные каналы — это транспорт IPC, поддерживаемый во всех версиях Windows. Именованные каналы хорошо интегрируются с безопасностью Windows для управления доступом клиента к каналу. В этой статье описывается настройка связи gRPC по именованным каналам.

Необходимые компоненты

  • .NET 8 или более поздней версии
  • Windows

Конфигурация сервера

Именованные каналы поддерживаются KestrelProgram.csв :

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

Предшествующий пример:

  • Настраивает конечные точки Kestrel в ConfigureKestrel.
  • Вызывает ListenNamedPipe прослушивание именованного канала с указанным именем.
  • Создает именованную конечную точку канала, которая не настроена для использования HTTPS. Дополнительные сведения о включении HTTPS см. в разделе о настройке конечной точки HTTPS Kestrel.

Настройка клиента

GrpcChannel поддерживает выполнение вызовов gRPC через настраиваемый транспорт. При создании канала его можно настроить с помощью SocketsHttpHandler, у которого имеется настраиваемый ConnectCallback. Обратный вызов позволяет клиенту устанавливать соединения через настраиваемые транспорты, а затем передавать HTTP-запросы через этот транспорт.

Примечание.

Некоторые функции GrpcChannelподключения, такие как балансировка нагрузки на стороне клиента и состояние канала, нельзя использовать вместе с именованными каналами.

Пример фабрики подключений именованных каналов:

public class NamedPipesConnectionFactory
{
    private readonly string pipeName;

    public NamedPipesConnectionFactory(string pipeName)
    {
        this.pipeName = pipeName;
    }

    public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,
        CancellationToken cancellationToken = default)
    {
        var clientStream = new NamedPipeClientStream(
            serverName: ".",
            pipeName: this.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;
        }
    }
}

Использование настраиваемой фабрики подключений для создания канала:

public static GrpcChannel CreateChannel()
{
    var connectionFactory = new NamedPipesConnectionFactory("MyPipeName");
    var socketsHttpHandler = new SocketsHttpHandler
    {
        ConnectCallback = connectionFactory.ConnectAsync
    };

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

Каналы, созданные с помощью предыдущего кода, отправляют вызовы gRPC через именованные каналы.