我知道这个问题之前已经针对不同的 .NET(Core)版本和框架设置进行过讨论。我已阅读答案和文档并进行了相应的实现(请参阅下面的参考资料和实现),但仍然无法在不同的机器上创建 gRPC HTTP/2 连接。
这意味着:没有加密的 gRPC工作正常如果
连接失败并出现所描述的异常。它尝试通过本地连接工作的同一网络接口进行连接。异常消息是:
Error starting gRPC Call. HttpRequestException: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to establish HTTP/2 connection.
参考文献我最初的问题是在单个主机上建立有效的客户端/服务器设置:提供输入以在 Winforms 应用程序中使用 gRPC 并建立未加密的连接。这基本上就是我现在使用的解决所描述问题的方法。
ASP.NET Core 中的 Kestrel Web 服务器文档指出 HTTP/2 只能通过 TLS 实现 - 但这样说是因为 TLS 包含协议协商。如果服务器和客户端都“预先同意”HTTP/2(我的设置就是这种情况),则不必像其他地方所述那样需要 TLS。
回答如何建立未加密的 HTTP/2 这就是我认为我正在做的 - 但如上所述,它只能在单个主机中工作。
实施细节服务器代码
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Host.UseNLog();
builder.Services.AddGrpc();
builder.Services.AddScoped<ICredentialManager, CredentialManager>();
builder.WebHost.ConfigureKestrel(options =>
{
// Setup a HTTP/2 endpoint without TLS.
options.Listen(System.Net.IPAddress.Any, ServerPort, listenOptions => listenOptions.Protocols = HttpProtocols.Http2);
});
var app = builder.Build();
Configure the HTTP request pipeline.
app.MapGrpcService<LoginService>();
... other services ...
app.MapGrpcService<TestingService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client.");
app.Run();
客户端代码options = new GrpcChannelOptions();
options.LoggerFactory = new NLog.Extensions.Logging.NLogLoggerFactory();
options.Credentials = ChannelCredentials.Insecure;
options.HttpHandler = new SocketsHttpHandler()
{
// Potentially set options here. No option for http versions available, though.
};
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// Only setting HttpHandler is supported by gRPC - setting default HttpClient causes exception; setting both, too.
// options.HttpClient = new HttpClient() { BaseAddress = new Uri(address), DefaultRequestVersion = new Version(2, 0) };
Channel = GrpcChannel.ForAddress(address, options);
var client = new Protos.Login.LoginClient(Channel);
来自日志的信息
2023-12-05 13:32:13.1584|INFO|Grpc.Net.Client.GrpcChannel|Proxy configuration is detected. How the gRPC client creates connections can cause unexpected behavior when a proxy is configured. To ensure the client correctly uses a proxy, configure GrpcChannelOptions.HttpHandler to use HttpClientHandler. Note that HttpClientHandler isn't compatible with load balancing.
2023-12-05 13:32:13.1915|DEBUG|Grpc.Net.Client.Internal.GrpcCall|Starting gRPC call. Method type: 'Unary', URI: 'http://172.15.15.30:5000/Login.Login/ClientLogin'.
2023-12-05 13:32:13.2091|DEBUG|Grpc.Net.Client.Balancer.Subchannel|Subchannel id '1-1' created with addresses: 172.15.15.30:5000
2023-12-05 13:32:13.2091|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Channel picker updated.
2023-12-05 13:32:13.2159|DEBUG|Grpc.Net.Client.Balancer.Subchannel|Subchannel id '1-1' state changed to Connecting. Detail: 'Connection requested.'.
2023-12-05 13:32:13.2159|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Channel state updated to Connecting.
2023-12-05 13:32:13.2159|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Picked queued.
2023-12-05 13:32:13.2404|DEBUG|Grpc.Net.Client.Balancer.Internal.SocketConnectivitySubchannelTransport|Subchannel id '1-1' connected to socket 172.15.15.30:5000.
2023-12-05 13:32:13.2404|DEBUG|Grpc.Net.Client.Balancer.Subchannel|Subchannel id '1-1' state changed to Ready. Detail: 'Successfully connected to socket.'.
2023-12-05 13:32:13.2404|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Channel state updated to Ready.
2023-12-05 13:32:13.2404|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Channel picker updated.
2023-12-05 13:32:13.2404|DEBUG|Grpc.Net.Client.Balancer.Internal.ConnectionManager|Successfully picked subchannel id '1-1' with address 172.15.15.30:5000. Transport status: InitialSocket
2023-12-05 13:32:13.2631|WARN|OptionHunter.Program|first-chance thread exception (Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to establish HTTP/2 connection.)
2023-12-05 13:32:13.2631|WARN|OptionHunter.Program| at System.Net.Http.HttpConnectionPool.ThrowGetVersionException(HttpRequestMessage request, Int32 desiredVersion, Exception inner)
也许这会导致这种奇怪的行为。当然,配置代理是有原因的,但仅限于外部连接。 gRPC 连接不需要。我会遵循建议,但这可能会有副作用。有没有办法告诉 gRPC“忽略任何代理设置,直接连接!”?
请注意,您的 Windows 设置没有配置不支持 http/2 的代理。.NET 将考虑并使用此代理,目前尚不清楚如何明确避免这种情况。不过,这是一个不同的问题。