如果grpc的客户端是阻塞式请求,那么默认是没有超时设置的,会一直等待。
grpc超时设置官方文档

超时一般在客户端调用请求接口是设置。分为同步与异步两种:

客户端同步请求的超时设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ClientContext context;
std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() +
std::chrono::milliseconds(100);
context.set_deadline(deadline);

// The actual RPC.
HelloRequest request;
request.set_heads(user);
HelloReply reply;
Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
std::string message = reply.message();
std::cout << message << std::endl;
} else {
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
}

表示超时时间为从当前时间到100ms之后。通过status.error_code()判断请求错误的具体原因。

另一种设置方式,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
gpr_timespec timespec;
timespec.tv_sec = 2; //设置阻塞时间为2秒
timespec.tv_nsec = 0;
timespec.clock_type = GPR_TIMESPAN;

ClientContext context;
context.set_deadline(timespec);

HelloRequest request;
request.set_heads(user);
HelloReply reply;
// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);
// Act upon its status.
if (status.ok()) {
std::string message = reply.message();
std::cout << message << std::endl;
}
else {
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
}

客户端异步请求的超时设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
HelloRequest request;
request.set_heads(user);

HelloReply reply;
ClientContext context;
CompletionQueue cq;
Status status;
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
stub_->AsyncSayHello(&context, request, &cq));

rpc->Finish(&reply, &status, (void*)1);
void* got_tag;
bool ok = false;

gpr_timespec time;
time.tv_sec = 2;//设置2秒超时
time.tv_nsec = 0;
time.clock_type = GPR_TIMESPAN;
CompletionQueue::NextStatus nextStatus =cq.AsyncNext(&got_tag, &ok, time);

if (nextStatus==GOT_EVENT) {
GPR_ASSERT(got_tag == (void*)1);
GPR_ASSERT(ok);
} else if(nextStatus==TIMEOUT) {
//超时
}

客户端超时重连

grpc客户端断线重连使用backoff机制。
重连间隔越来越长。
可以通过参数指定相关参数。
相关参数:

1
2
3
4
5
6
7
::grpc_impl::ChannelArguments args;
args.SetInt(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 100);
args.SetInt(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 100);
args.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 100);
std::shared_ptr<grpc_impl::Channel> channel = grpc::CreateCustomChannel("localhost:8081", grpc::InsecureChannelCredentials(), args);

std::unique_ptr<arc::MyService::Stub> stub(arc::MyService::NewStub(channel));

服务端超时设置

1
2
3
4
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_TIME_MS, 5000);
builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 10000);
builder.AddChannelArgument(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);

参数的意义在源码中有解释, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/** After a duration of this time the client/server pings its peer to see if the
transport is still alive. Int valued, milliseconds. */
#define GRPC_ARG_KEEPALIVE_TIME_MS "grpc.keepalive_time_ms"
/** After waiting for a duration of this time, if the keepalive ping sender does
not receive the ping ack, it will close the transport. Int valued,
milliseconds. */
#define GRPC_ARG_KEEPALIVE_TIMEOUT_MS "grpc.keepalive_timeout_ms"
/** Is it permissible to send keepalive pings without any outstanding streams.
Int valued, 0(false)/1(true). */
#define GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS \
"grpc.keepalive_permit_without_calls"
/** Default authority to pass if none specified on call construction. A string.
* */