【问题标题】:When making Grpc request over http in .net core creates following exception. I am using .net core 3.1在 .net 核心中通过 http 发出 Grpc 请求时会产生以下异常。我正在使用 .net 核心 3.1
【发布时间】:2020-08-31 02:32:12
【问题描述】:
Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The request was aborted. Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).", DebugException="System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.IO.IOException: The request was aborted.
 ---> System.Net.Http.Http2ConnectionException: The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'PROTOCOL_ERROR' (0x1).
   at System.Net.Http.Http2Connection.ReadFrameAsync(Boolean initialFrame)
   at System.Net.Http.Http2Connection.ProcessIncomingFramesAsync()
   --- End of inner exception stack trace ---
   at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
   at System.Net.Http.Http2Connection.Http2Stream.TryEnsureHeaders()
   at System.Net.Http.Http2Connection.Http2Stream.ReadResponseHeadersAsync(CancellationToken cancellationToken)
   at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Grpc.Net.Client.Internal.GrpcCall`2.RunCall(HttpRequestMessage request, Nullable`1 timeout)")
   at API.Controllers.WeatherForecastController.GetToken(UserDetails aUserDetails) in C:\DotNetCoreFramework -DBAgnostic\Test\API\Controllers\WeatherForecastController.cs:line 80
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted).
      public UserDetails GetToken(UserDetails aUserDetails)
        {
            try
            {
                AppContext.SetSwitch(
                    "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

                using GrpcChannel channel1 = Grpc.Net.Client.GrpcChannel.ForAddress("http://localhost:5009/");
                var client1 = new Greeter.GreeterClient(channel1);
                UserDetails lUserDetails = client1.GetToken(aUserDetails);
                return lUserDetails;
            }catch(Exception ex) 
            {
                throw ex;
            }
         
        }```
port no in Grpc Service and client is same.

【问题讨论】:

  • 这里有同样的问题。你明白了吗?

标签: c# asp.net-core grpc


【解决方案1】:

结合前面的答案,我想出了这个简单的解决方案。您无需更改任何代码,只需 appsettings.json。示例:

  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001"
      },
      "Grpc": {
        "Url": "http://localhost:5002",
        "Protocols": "Http2"
      }
    }
  }

【讨论】:

    【解决方案2】:

    在我的 program.cs 文件中,我使用 UseUrls 设置为“http://localhost/5009”,而在 appsettings.json kestrel 部分如下

    "Kestrel": {
        "Endpoints": {
          "HttpsInlineCertFile": {
            "Url": "https://localhost:5010",`enter code here`
            "Protocols": "Http2"
          }
          //,
          //"EndpointDefaults": {
          //  "Url": "http://localhost:5001",
          //  "Protocols": "Http2"
          //}
        }
      }
    

    我删除了 appsettings.json 中的 kestrel 部分,一切正常

    【讨论】:

      【解决方案3】:

      我可以这样解决:

       public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
              WebHost.CreateDefaultBuilder(args)
                  .UseConfiguration(Configuration)
                  .ConfigureKestrel(options =>
                  {
                      var (httpPort, grpcPort) = GetDefinedPorts();
      
                      options.Listen(IPAddress.Any, httpPort, listenOptions =>
                      {
                          listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
                          listenOptions.UseHttps();
                      });
      
                      options.Listen(IPAddress.Any, grpcPort, listenOptions =>
                      {
                          listenOptions.Protocols = HttpProtocols.Http2;
                      });
                  })
                  .UseStartup<Startup>();
      
          private static (int httpPort, int grpcPort) GetDefinedPorts()
          {
              var grpcPort = Configuration.GetValue("GRPC_PORT", 5000);
              var port = Configuration.GetValue("PORT", 5001);
      
              return (port, grpcPort);
          }
      

      基本上我配置了两个端口:

      • 5001上支持HTTP 1和2HTPPS端口,然后我可以打开'localhost:50001/swagger'李>
      • 另一个使用 HTTP 且仅支持 HTTP2 用于 gRPC 连接的端口。

      【讨论】:

        猜你喜欢
        • 2021-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-08
        • 2021-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多