Skip to content

gRPC over Named Pipes - Alternative for client-side load balancing, channel status? #34620

@EddyHaigh

Description

@EddyHaigh

Description

Problem

When creating a basic gRPC over Named Pipes application from the code of the documentation, the code breaks with the following error code on the channel.ConnectAsync();.

Even though there is a note about regarding the things mentioned it doesn't explain anything about how to disable.

System.InvalidOperationException: 'Channel is configured with an HTTP transport doesn't support client-side load balancing or connectivity state tracking. The underlying HTTP transport must be a SocketsHttpHandler with no SocketsHttpHandler.ConnectCallback configured. The HTTP transport must be configured on the channel using GrpcChannelOptions.HttpHandler.'

Code

Server

Program.cs

using GrpcService1.Services;

using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddGrpc();

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

var app = builder.Build();

// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();

app.Run();

Client

NamedPipesConnectionFactory.cs

using Grpc.Net.Client;

using System.IO.Pipes;
using System.Security.Principal;

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

Program.cs

// See https://aka.ms/new-console-template for more information
using GrpcService1;

var channel = NamedPipesConnectionFactory.CreateChannel();

await channel.ConnectAsync();

var greeter = new Greeter.GreeterClient(channel);

do
{
    await greeter.SayHelloAsync(new HelloRequest { Name = "World" });

} while (true);

Page URL

https://learn.microsoft.com/en-us/aspnet/core/grpc/interprocess-namedpipes?view=aspnetcore-9.0

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/grpc/interprocess-namedpipes.md

Document ID

58d486b8-0e04-9767-2089-deb43a28f56b

Article author

@JamesNK

Metadata

  • ID: 58d486b8-0e04-9767-2089-deb43a28f56b
  • Service: aspnet-core
  • Sub-service: grpc

Related Issues

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions