Sdílet prostřednictvím


Komunikace mezi procesy s gRPC a pojmenovanými kanály

Autor: James Newton-King

.NET podporuje komunikaci mezi procesy (IPC) pomocí gRPC. Další informace o tom, jak začít používat gRPC ke komunikaci mezi procesy, najdete v tématu Komunikace mezi procesy s gRPC.

Pojmenované kanály jsou přenosY IPC podporované ve všech verzích Windows. Pojmenované kanály se dobře integrují se zabezpečením Windows a řídí klientský přístup k kanálu. Tento článek popisuje, jak nakonfigurovat komunikaci gRPC přes pojmenované kanály.

Požadavky

  • .NET 8 nebo novější
  • Windows

Konfigurace serveru

Pojmenované kanály jsou podporovány Kestrel, který je nakonfigurován v Program.cs:

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

Předchozí příklad:

  • Konfiguruje Kestrelkoncové body v ConfigureKestrel.
  • Volání ListenNamedPipe pro naslouchání pojmenovaného kanálu se zadaným názvem.
  • Vytvoří pojmenovaný koncový bod kanálu, který není nakonfigurovaný tak, aby používal PROTOKOL HTTPS. Informace o povolení PROTOKOLU HTTPS najdete v tématu Kestrel Konfigurace koncového bodu HTTPS.

Konfigurace PipeSecurity pro pojmenované kanály

Pokud chcete určit, kteří uživatelé nebo skupiny se můžou připojit, použijte NamedPipeTransportOptions třídu. To umožňuje zadat vlastní PipeSecurity objekt.

Příklad:

using Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes;
using System.IO.Pipes;
using System.Security.AccessControl;

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

        // Configure PipeSecurity
        listenOptions.UseNamedPipes(options =>
        {
            var pipeSecurity = new PipeSecurity();
            // Grant read/write access to the Users group
            pipeSecurity.AddAccessRule(new PipeAccessRule(
                "Users",
                PipeAccessRights.ReadWrite,
                AccessControlType.Allow));
            // Add additional rules as needed

            options.PipeSecurity = pipeSecurity;
        });
    });
});

Předchozí příklad:

  • Používá UseNamedPipes k přístupu a konfiguraci NamedPipeTransportOptions.
  • PipeSecurity Nastaví vlastnost, která určuje, kteří uživatelé nebo skupiny se mohou připojit k pojmenované kanálu.
  • Udělí skupině Users přístup pro čtení a zápis. Podle potřeby je možné přidat další pravidla zabezpečení.

Přizpůsobení Kestrel koncových bodů pojmenovaného kanálu

KestrelPodpora pojmenovaného kanálu umožňuje pokročilé přizpůsobení, které umožňuje konfigurovat různá nastavení zabezpečení pro každý koncový bod pomocí této CreateNamedPipeServerStream možnosti. Tento přístup je ideální pro scénáře, kdy více koncových bodů pojmenovaného kanálu vyžaduje jedinečné řízení přístupu. Možnost přizpůsobení kanálů na koncový bod je dostupná od .NET 9.

Příkladem, kde je to užitečné, je Kestrel aplikace, která vyžaduje dva koncové body kanálu s odlišným zabezpečením přístupu. Možnost CreateNamedPipeServerStream lze použít k vytváření kanálů s vlastním nastavením zabezpečení v závislosti na názvu kanálu.


var builder = WebApplication.CreateBuilder();
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenNamedPipe("pipe1");
    options.ListenNamedPipe("pipe2");
});

builder.WebHost.UseNamedPipes(options =>
{
    options.CreateNamedPipeServerStream = (context) =>
    {
        var pipeSecurity = CreatePipeSecurity(context.NamedPipeEndpoint.PipeName);

        return NamedPipeServerStreamAcl.Create(context.NamedPipeEndpoint.PipeName, PipeDirection.InOut,
            NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte,
            context.PipeOptions, inBufferSize: 0, outBufferSize: 0, pipeSecurity);
    };
});

Konfigurace klienta

GrpcChannel podporuje volání gRPC přes vlastní přenosy. Po vytvoření kanálu je možné ho nakonfigurovat pomocí SocketsHttpHandler vlastního ConnectCallbackkanálu . Zpětné volání umožňuje klientovi vytvářet připojení přes vlastní přenosy a poté odesílat požadavky HTTP přes tento přenos.

Poznámka:

Některé funkce GrpcChannelpřipojení , jako je vyrovnávání zatížení na straně klienta a stav kanálu, se nedají používat společně s pojmenovanými kanály.

Příklad připojení pojmenovaných kanálů:

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

Vytvoření kanálu pomocí vlastní továrny pro připojení:

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

Kanály vytvořené pomocí předchozího kódu odesílají volání gRPC přes pojmenované kanály.