.net Core Grpc 客户端无法调用 Greeter 服务

Posted

技术标签:

【中文标题】.net Core Grpc 客户端无法调用 Greeter 服务【英文标题】:.net Core Grpc Client unable to call Greeter Service 【发布时间】:2020-08-14 18:50:23 【问题描述】:

我已经看了很长时间了,浏览了互联网上所有不同的帖子,看看我是否能找到有同样问题的人,但不知何故,我似乎是唯一遇到这个问题的人。

我有一个 ASP.net Core 服务器运行 Grpc 的基本欢迎服务。 使用程序“BloomRPG”调用此服务器效果很好,并且响应时间极好。 但是,当我尝试从自己编写的(非常基本的)客户端执行相同操作时,出现以下错误:

在客户端:

dbug:Grpc.Net.Client.Internal.GrpcCall[1] 启动 gRPC 调用。方法类型:“一元”,URI:“https://www.MYSERVER.com:50005/greet.Greeter/SayHello”。 dbug:Grpc.Net.Client.Internal.GrpcCall[18] 发送消息。 trce:Grpc.Net.Client.Internal.GrpcCall[21] 将“TestService1.HelloRequest”序列化为 15 字节消息。 trce:Grpc.Net.Client.Internal.GrpcCall[19] 消息已发送。 失败:Grpc.Net.Client.Internal.GrpcCall[6] 启动 gRPC 调用时出错。 System.Net.Http.HttpRequestException:发送请求时出错。 ---> System.IO.IOException:响应提前结束。 在 System.Net.Http.HttpConnection.FillAsync() 在 System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(布尔 foldedHeadersAllowed) 在 System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage 请求,CancellationToken cancelToken) --- 内部异常堆栈跟踪结束 --- 在 System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage 请求,CancellationToken cancelToken) 在 System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection 连接,HttpRequestMessage 请求,布尔 doRequestAuth,CancellationToken 取消令牌) 在 System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage 请求,布尔 doRequestAuth,CancellationToken 取消令牌) 在 System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage 请求,CancellationToken cancelToken) 在 System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage 请求,CancellationToken cancelToken) 在 System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at Grpc.Net.Client.Internal.GrpcCall2.RunCall(HttpRequestMessage 请求, Nullable1 timeout) info: Grpc.Net.Client.Internal.GrpcCall[3] Call failed with gRPC error status. Status code: 'Internal', Message: 'Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The response ended prematurely.'. dbug: Grpc.Net.Client.Internal.GrpcCall[4] Finished gRPC call. dbug: Grpc.Net.Client.Internal.GrpcCall[8] gRPC call canceled. Unhandled exception. Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. HttpRequestException: An error occurred while sending the request. IOException: The response ended prematurely.", DebugException="System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.IO.IOException: The response ended prematurely. at System.Net.Http.HttpConnection.FillAsync() at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed) at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, 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 System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task1 sendTask, HttpRequestMessage 请求, CancellationTokenSource cts, Boolean disposeCts) 在 Grpc.Net.Client.Internal.GrpcCall2.RunCall(HttpRequestMessage request, Nullable1 超时)") 在 C:\Users\MYUSERNAME\source\repos\grpc\TestgrpcClient\TestgrpcClient\Program.cs:line 64 中的 GrpcGreeterClient.Program.Main(String[] args) 在 GrpcGreeterClient.Program.(String[] args) s

在服务器上:

失败:Microsoft.AspNetCore.Server.Kestrel[0] HTTP/2 over TLS 不是在仅 HTTP/2 的端点上协商的。

由于我使用 BloomRPC 成功调用服务,我想问题出在我的客户端上:

客户端代码:

        AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);


        var loggerFactory = LoggerFactory.Create(logging =>
        
            logging.AddConsole();
            logging.SetMinimumLevel(LogLevel.Trace);
        );


        var httpclient = new HttpClient();
        httpclient.DefaultRequestVersion = new Version(2, 0);

        




        using var channel = GrpcChannel.ForAddress("https://www.MYSERVER.com:50005",
            new GrpcChannelOptions  LoggerFactory = loggerFactory, HttpClient = httpclient);
        

        var client = new Greeter.GreeterClient(channel);
        
        var reply = await client.SayHelloAsync(
                          new HelloRequest  Name = "GreeterClient" );
        Console.WriteLine("Greeting: " + reply.Message);
        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
        

有人知道我接下来可以尝试什么吗? 我觉得我已经用尽了所有的选择:(

【问题讨论】:

您遇到 TLS 身份验证错误。 TJS 1.0/1.1 已于 6 月停产,您必须使用 TLS 1.2 确保您拥有最新的 API 和 dll。旧版本不适用于 TLS 1.2。此外,如果您使用任何示例代码,请确保您拥有最新的代码。 好的,我已经添加了一个 httpclienthandler,它从上面强制在 httpclient 的构造函数中使用 TLS 1.2,但它给出了完全相同的错误。在电脑上转到 Internet 选项显示 TLS 1.2 已启用 不再编辑该评论?无论如何,我也觉得有必要添加我使用自包含客户端,所以这应该意味着对主机没有依赖关系吧?我尝试从另一台计算机执行并且客户端工作,但不是从第一台计算机执行。所以不是客户端的问题,而是计算机的问题? 使用像wireshark或fiddler这样的嗅探器,比较第一个工作请求和一个不工作的请求。存在错误或未设置的默认标头。 用 Wireshark 进行实验表明有公司代理服务器在干扰。我的猜测是,这会阻止我的客户建立良好的连接。我剩下的唯一问题是:为什么同一台电脑上的 BloomRPC 可以工作?不应该有同样的干扰吗? 【参考方案1】:

感谢@jdweng,我找到了导致问题的原因。

强制公司代理服务器出现干扰,在 httpclienthandler 中设置 UseProxy = false 为我解决了这个问题,我现在可以毫无问题地调用我的 gRPC 服务器!

【讨论】:

以上是关于.net Core Grpc 客户端无法调用 Greeter 服务的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core 3.0 gRPC框架小试

gRPC在 ASP.NET Core 中应用学习

[.Net Core] - 在 .NET Core 中创建 gRPC 服务端和客户端

ASP.NET Core gRPC 拦截器的使用技巧分享

何时应该使用 Pipes 或 gRPC 进行进程间通信(在 C# .NET Core 中)?

.NET Core gRPC 拦截器的使用技巧分享