【问题标题】:.Net Core 3.1 gRPC client with unencrypted HTTP2 connection具有未加密 HTTP2 连接的 .Net Core 3.1 gRPC 客户端
【发布时间】:2021-08-03 21:36:12
【问题描述】:

我正在尝试查询一些在 HTTP 上运行的本地 gRPC 服务。这是我的 net core 3.1 控制台应用程序:

static async Task Main(string[] args)
{
    AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

    using var channel = GrpcChannel.ForAddress("http://localhost:16050");
    var client = new EventService.EventServiceClient(channel);
    var reply1 = await client.GetTrackEventAsync(new GetTrackEventRequest { Name = "01Austra14" });
}

但它抛出了这个错误:

“Grpc.Core.RpcException”类型的异常发生在 System.Private.CoreLib.dll 但未在用户代码中处理: 'Status(StatusCode="Internal", Detail="启动 gRPC 调用时出错。 HttpRequestException:发送请求时发生错误。 Http2ConnectionException:HTTP/2 服务器在 联系。 HTTP/2 错误代码 'PROTOCOL_ERROR' (0x1)。", DebugException="System.Net.Http.HttpRequestException: 一个错误 发送请求时发生。 ---> System.Net.Http.Http2ConnectionException:HTTP/2 服务器发送 连接上的无效数据。 HTTP/2 错误代码“PROTOCOL_ERROR” (0x1)。

不幸的是,目前我们无法添加 SSL 证书,并且我们需要使用纯 HTTP 一段时间(服务应用程序尚未投入生产)。有人知道这里发生了什么吗?

根据documentationAppContext.SetSwitch 调用应该足够了。

服务器是一个 Asp Net Core 3.1 应用程序。它正在运行:

  • 端口http://*:16050
  • 端口 https://*:16150。 这会正确回复客户,但如上所述,目前只能在本地使用

服务器提供

  • Http1 和 Http2
  • REST API 和 gRPC API 在同一个端口上

客户端正在使用以下包

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.17.0" />
    <PackageReference Include="Grpc.Net.Client" Version="2.37.0" />
    <PackageReference Include="Grpc.Tools" Version="2.37.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

【问题讨论】:

  • 您可以解决它。请阅读我提供的链接。我过去已经这样做了
  • @phuzi 不正确; gRPC 和 HTTP/2 在没有 TLS 的情况下也能正常工作 - 只是不推荐,需要一个选择加入开关
  • 链接失效
  • 链接已修复,指向 ms doc

标签: c# asp.net-core .net-core grpc


【解决方案1】:

我不能 100% 确定这适用于您的场景(尽管“Http1 和 Http2”建议:它会适用),但是:我已经看到这个问题与尝试服务的非 TLS 端点有关HTTP/1 和 HTTP/2 流量 - 它有点困惑,并尝试用 HTTP/1 响应来响应 HTTP/2 请求(这不会发生在 TLS 端点上,因为握手的工作方式不同)。就我而言,解决方法是告诉服务器服务 HTTP/2。这可以在 Kestrel / EndPoints 节点下的 appSettings.json 中通过指定 "Protocols": "Http2" 或在 Program.cs 中通过在 ConfigureKestrel 调用中指定 listenOptions.Protocols = HttpProtocols.Http2 来完成。当我想在没有 TLS 的情况下提供 HTTP/1 和 HTTP/2 时,我总是不得不使用不同的端口等。

【讨论】:

  • 太好了,这解决了!非常感谢。但是现在在 Docker 中运行时似乎无法连接到“外部世界”?我无法 ping 它,它也无法连接到本地数据库。 110% 确定在仅切换到 http 2 之前没有发生这种情况
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
相关资源
最近更新 更多