在 .NET 中建立不加密的 gRPC 连接

问题描述 投票:0回答:1

总结

我知道这个问题之前已经针对不同的 .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 这就是我认为我正在做的 - 但如上所述,它只能在单个主机中工作。

实施细节

运行时

我使用 C# 和 .NET 7 以及 Microsoft.NETCore.App Microsof.AspNetCore.App 以及 GrpcAspNetCore 2.57.0。

服务器代码

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“忽略任何代理设置,直接连接!”?

c# .net grpc http2 kestrel-http-server
1个回答
0
投票
结束本主题:我最初提供的代码确实是为 gRPC 建立未加密的 http/2 连接的正确代码。

请注意,您的 Windows 设置没有配置不支持 http/2 的代理。.NET 将考虑并使用此代理,目前尚不清楚如何明确避免这种情况。不过,这是一个不同的问题。

© www.soinside.com 2019 - 2024. All rights reserved.