Nguon: Microsoft Learn · .NET 8.0

Giao tiếp liên tiến trình với gRPC và Unix domain sockets

Nguồn: Inter-process communication with gRPC and Unix domain sockets

Bởi James Newton-King

.NET hỗ trợ giao tiếp liên tiến trình (IPC - inter-process communication) sử dụng gRPC. Để biết thêm thông tin về cách bắt đầu sử dụng gRPC để giao tiếp giữa các tiến trình, xem Giao tiếp liên tiến trình với gRPC.

Unix domain sockets (UDS) là một transport (giao thức truyền tải) IPC được hỗ trợ rộng rãi, hiệu quả hơn TCP khi client và server nằm trên cùng một máy. Bài viết này trình bày cách cấu hình giao tiếp gRPC qua UDS.

Yêu cầu tiên quyết

Cấu hình server

Unix domain sockets được hỗ trợ bởi Kestrel, được cấu hình trong Program.cs:

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

Ví dụ trên:

Cấu hình client

GrpcChannel hỗ trợ thực hiện các gRPC call qua các transport tùy chỉnh. Khi một channel được tạo, nó có thể được cấu hình với một SocketsHttpHandlerConnectCallback tùy chỉnh. Callback này cho phép client thực hiện kết nối qua các transport tùy chỉnh và sau đó gửi các HTTP request qua transport đó.

Lưu ý: Một số tính năng kết nối của GrpcChannel, như client side load balancing (cân bằng tải phía client) và channel status (trạng thái channel), không thể sử dụng cùng với Unix domain sockets.

Ví dụ về Unix domain sockets connection factory (nhà máy kết nối):

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

Sử dụng custom connection factory để tạo channel:

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

Các channel được tạo bằng code trên sẽ gửi các gRPC call qua Unix domain sockets.