.NET 5 GRPC 客户端调用抛出异常:在未启用 HTTP/2 时请求具有版本策略 RequestVersionOrHigher 的 HTTP 版本 2.0

.NET 5 GRPC client call throws exception: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while HTTP/2 is not enabled

这是我的第一个 gRPC 应用程序。我正在尝试从 .NET 5 gRPC 客户端 (Grpc.Net.Client 2.35.0) 调用服务器流式 RPC 调用,这导致我的本地开发环境出现以下异常:

Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while HTTP/2 is not enabled."

无论服务器应用程序是否为 运行,都会发生这种情况。这是我用来拨打电话的代码:

using var channel = GrpcChannel.ForAddress(@"http://localhost:5000");
var client = new AlgorithmRunner.AlgorithmRunnerClient(channel);
using var call = client.RunAlgorithm(new RunAlgorithmRequest());

while (await call.ResponseStream.MoveNext())
{

}

我的理解是 .NET 5 gRPC 应该默认启用 HTTP/2:为什么异常显示 HTTP/2 未启用,我该如何解决?

经过进一步调查,这似乎与我机器上的代理设置有关,而代理设置与我公司的网络设置有关。具体来说,我定义了以下环境变量:

http_proxy https_proxy

.NET 从这些环境变量中填充 HttpClient DefaultProxy。我的公司代理似乎在干扰 HTTP/2(不受支持?),导致 gRPC 无法正常工作。本地开发的解决方法是在进行 gRPC 调用之前手动设置 HttpClient 的默认代理:

HttpClient.DefaultProxy = new WebProxy();
                
using var channel = GrpcChannel.ForAddress(@"http://localhost:5000");
var client = new AlgorithmRunner.AlgorithmRunnerClient(channel);
using var call = client.RunAlgorithm(new RunAlgorithmRequest());

这可能代表通过某些类型的代理使用 gRPC 时的普遍问题。

我在公司代理后面遇到同样的问题并收到此错误消息

An exception of type 'Grpc.Core.RpcException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Status(StatusCode="Unavailable", Detail="Error starting gRPC call. HttpRequestException: Connection refused SocketException: Connection refused", DebugException="System.Net.Http.HttpRequestException: Connection refused

我完全同意您建议的通过覆盖 DefaultProxy 绕过所有代理设置的解决方法是合法且有效的。

稍微好一点的方法是不在代码中硬编码 'bypass all proxy statement',而是使用 no_proxy 环境变量。 这个环境变量的目的是定义一个规则来排除发往某些主机的流量

解决方案

激活环境。变量 no_proxy 用于您的开发设置,例如

对于linux

export no_proxy=localhost,127.0.0.1

对于 Dockerfile

ENV no_proxy=localhost,127.0.0.1

有关 proxy environment variables

的深入探讨

启动 gRPC 客户端应用程序时,请务必检查环境变量中读取的值,因为 gRPC 使用 HttpClient class在引擎盖下,它考虑了所有代理环境变量。如果没有设置no_proxy值,则没有效果。

var noProxy = Environment.GetEnvironmentVariable("no_proxy");