You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET无加密gRPC跨机器HTTP/2连接失败求助

无加密gRPC跨机器连接异常(忽略代理)解决方案

问题概述

在.NET 7环境中搭建无加密gRPC服务,本地客户端连接localhost或本地网卡的服务端可正常通信,但跨机器连接时抛出异常:

Error starting gRPC Call. HttpRequestException: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to establish HTTP/2 connection.

服务端已配置Kestrel监听任意IP的HTTP/2端口,客户端已开启System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport开关并使用ChannelCredentials.Insecure,但日志显示检测到代理配置,推测是代理影响了跨机器连接,需求是让gRPC忽略代理直接建立连接。

相关代码与日志

服务端代码

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.2631|WARN|OptionHunter.Program|first-chance thread exception (Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to establish HTTP/2 connection.)

解决方案

1. 配置SocketsHttpHandler直接禁用代理

修改客户端的SocketsHttpHandler配置,明确禁用代理并指定HTTP/2版本策略,确保客户端直接与服务端建立连接:

options = new GrpcChannelOptions();
options.LoggerFactory = new NLog.Extensions.Logging.NLogLoggerFactory();
options.Credentials = ChannelCredentials.Insecure;
options.HttpHandler = new SocketsHttpHandler()
{
    UseProxy = false, // 禁用代理,直接连接服务端
    DefaultRequestVersion = HttpVersion.Version20,
    DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher
};
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

Channel = GrpcChannel.ForAddress(address, options);

var client = new Protos.Login.LoginClient(Channel);

2. 清除系统代理环境变量(可选)

如果客户端机器存在全局代理环境变量(如HTTP_PROXY、HTTPS_PROXY),可以在创建gRPC通道前临时清除这些变量,避免被自动读取:

// 在初始化GrpcChannel前执行
Environment.SetEnvironmentVariable("HTTP_PROXY", null);
Environment.SetEnvironmentVariable("HTTPS_PROXY", null);

3. 验证服务端网络连通性

确认服务端的指定端口未被防火墙、安全组拦截,可通过telnet 服务端IP 端口或nc -zv 服务端IP 端口命令测试跨机器端口是否可达。

原因说明

代理服务器通常默认不支持无加密的HTTP/2连接,客户端尝试通过代理建立HTTP/2连接时会失败,进而触发版本不匹配的异常。直接禁用代理后,客户端会直接与服务端建立无加密的HTTP/2连接,解决跨机器通信问题。

内容的提问来源于stack exchange,提问作者jowo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:02:42