dotnet / dotnet/AspNetCore.Docs
gRPC over Named Pipes - Alternative for client-side load balancing, channel status?
- Dominant language
- C#
- Stars
- 13.1k
- Forks
- 24.6k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 97
Description
### 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
```csharp
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();
app.Run();
```
### Client
#### NamedPipesConnectionFactory.cs
```csharp
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 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
```csharp
// 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](https://github.com/dotnet/AspNetCore.Docs/issues?q=is%3Aissue+is%3Aopen+58d486b8-0e04-9767-2089-deb43a28f56b)
Contributor guide
Assessment
This issue has not been assessed yet.