网络重置后,客户端通道无法使用

时间:2019-04-01 16:54:37

标签: c++ grpc

摘要:如果客户端通道处于READY状态并且网络断开连接,则该通道将变得不可用,并且一旦重新建立网络连接,客户端将不会尝试重新连接到服务器。 。发生READY错误(由我的客户端应用程序设置的最后期限)后,通道不会从TRANSIENT_FAILURE状态转换为DEADLINE_EXCEEDED

您使用的是什么版本的gRPC和使用什么语言?

1.17.2 在1.11.x版中有相同的发行经验 C ++

什么操作系统(Linux,Windows等)和版本?

在Ubuntu 16.04上运行的客户端。 运行Windows Enterprise的服务器。

您做了什么?

服务器和客户端都在连接的网络上启动。我可以成功拨打电话并从服务器接收响应。当网络关闭时,服务器会收到"Disconnected client - Endpoint read failed"错误。此调试消息中的其他一些相关字段-"grpc_status":14 (UNAVAILABLE), "occured_during_write":0, "description":"An established connection was aborted by the software in your host machine"

在断开网络连接时,客户端根本不会打印出任何日志(使用GRPC_TRACE=connectivity_state,call_error,op_failure,server_channel,client_channel,channel GRPC_VERBOSITY=DEBUG)。

再次打开网络后,服务器和客户端上都不会遇到日志。尝试使用客户端进行呼叫(发送启动请求)会导致重复的DEADLINE_EXCEEDED错误。此时关闭网络连接不会导致服务器端"Disconnected client"错误。

客户端上下文设置为使用截止日期(经过2秒和10秒测试)。在这种情况下,将使用同步调用。

代码段:

/rpc_service.proto

syntax = "proto3";

import "google/rpc/status.proto";

message RpcRequest {
}

message RpcResponse {
}

service RpcService{
rpc Call(RpcRequest) returns (RpcResponse);
}

/client.cc

初始化:

std::unique_ptrRpcService::Stub stub_ = RpcService::NewStub(::grpc::CreateChannel(
server_endpoint, ::grpc::InsecureChannelCredentials()));

发送rpc请求:

::grpc::ClientContext context;
context.set_deadline(
gpr_time_from_micros(call_timeout_.InMicroseconds(), GPR_TIMESPAN));
RpcRequest request;
RpcResponse response;
::grpc::Status grpc_status = stub_->Call(&context, request, &response);

/server.cc

grpc::ServerBuilder builder;
builder.AddListeningPort(endpoint, ::grpc::InsecureServerCredentials());
builder.RegisterService(&rpc_service);
std::unique_ptrgrpc::Server grpc_server_ = builder.BuildAndStart();

您期望看到什么?

网络重置后,客户应成功拨打电话。

您看到了什么?

客户端无法从服务器收到响应。

我们还应该了解您的项目/环境吗?

当重新建立网络连接并且客户端无法从服务器接收响应时,tcpdump会捕获客户端发送一些数据包。 在打开网络的情况下启动客户端和服务器,然后拔出网络的连接不会导致任何错误消息,直到尝试进行呼叫为止。这与在断开网络连接的情况下启动客户端和服务器时的结果相同。尝试拨打电话后,客户端将从IDLE转换为CONNECTING,然后开始在CONNECTINGTRANSIENT_FAILURE状态之间来回跳动(尝试以指数级的反向连接来重新连接)关闭),直到重新建立连接。

如果客户端在连接网络的情况下启动,但未发送请求并且网络断开,则服务器不会收到客户端断开的错误。在拨打电话之前,客户将停留在"IDLE"中。

如果客户端初始化并且在断开连接的网络上进行呼叫,则客户端将进入CONNECTING状态(指数回退最多2分钟,此时客户端将处于{{ 1}}状态)。连接网络后,下一次通道将进入TRANSIENT_FAILURE状态,客户端将进入CONNECTING状态时,将重新建立连接。此后,每个呼叫将成功,直到重置网络。 客户端处于READY状态后断开网络连接不会使客户端脱离READY状态。

总而言之:在未进行呼叫之前,无论网络状态如何,客户端都将保持READY状态。拨打电话后,客户端将尝试通过进入"IDLE"状态来建立连接。如果未找到连接,它将在CONNECTINGCONNECTING状态之间转换反弹。找到连接后,客户端将进入TRANSIENT_FAILURE状态。从这里开始,如果连接断开,客户端将不会再次尝试进入READY状态。

与我遇到的类似问题(已结束)

https://github.com/grpc/grpc/issues/16974

已知修补程序:

在每次通话中创建一个新频道。

修复尝试失败:

CONNECTING

问题:

网络重置后,客户端是否可以使用已创建的频道?

重置网络后是否必须重新启动频道?

注意::我在grpc github上打开了一张票,并且在5天内没有收到任何回复,所以我也在这里发布。链接到grpc github问题:https://github.com/grpc/grpc/issues/18554

0 个答案:

没有答案