首页 > 解决方案 > Grpc C++:如何等到一元请求被发送?

问题描述

我正在围绕 gRPC 一元调用编写一个包装器,但是我遇到了一个问题:假设我有一个ClientAsyncResponseReader对象,它被创建并像这样启动一个请求

response_reader_ = std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
        grpc::internal::ClientAsyncResponseReaderFactory<ResponseType>::Create(
            channel.get(), completion_queue, rpc_method, &client_context_, request, true
        )
);
response_reader_->Finish(
    response_sharedptr_.get(), status_sharedptr_.get(), static_cast<void*>(some_tag)
);
// Set a breakpoint here

所有论点都是有效的。

我的印象是,当Finish调用返回时,request可以保证该对象已通过网络发送出去。但是,通过在 Finish() 调用之后设置断点(在客户端程序中,要清楚)并检查我的服务器日志,我发现服务器request直到我从断点恢复后才记录。

这似乎表明我需要等待其他一些事情以确保真正发出请求:此外,执行上述代码的线程在发出请求时仍然具有某种作用-断点。

当然,也许我的假设是错误的,并且服务器没有在请求进入时立即记录它。如果不是,那么显然我没有像我应该的那样理解 gRPC 的语义,所以我希望更多经验丰富的洞察力。

您可以在此处查看我的一元调用抽象的代码。这应该足够了,但如果需要其他任何东西,我很乐意提供。

编辑:情节变厚了。在服务器的处理程序上为传入请求设置断点后,看起来对 Finish 的调用通常确实“确保”请求已发送出去:除了进程发送的第一个请求。我想有一些状态保持在grpc::channel或者甚至在grpc::completion_queue延迟初始请求中

标签: grpcgrpc-c++

解决方案


从文档

response_reader_ = std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
        grpc::internal::ClientAsyncResponseReaderFactory<ResponseType>::Create(
            channel.get(), completion_queue, rpc_method, &client_context_, request, true
        )
);

这将启动一个调用并写出请求(start=true)。此函数没有标签参数。因此,完成队列无法通知呼叫开始何时完成。调用 RPC 方法有点复杂,它主要涉及创建网络数据包并将其放入网络中。如果传输暂时失败或通道完全消失或用户做了一些愚蠢的事情,它可能会失败。另一件事,为什么我们需要标签通知是完成队列实际上是一个争用点。所有 RPC 对象都与此对话,可能会发生完成队列不是空闲的并且请求仍处于未决状态。

response_reader_->Finish(
    response_sharedptr_.get(), status_sharedptr_.get(), static_cast<void*>(some_tag)

这将请求 RPC 运行时接收服务器的响应。输出是当服务器响应到达时,完成队列将通知客户端。在此刻。我们假设客户端没有错误,一切正常并且请求已经在进行中。因此,对于一元 rpc,Finish 调用的状态永远不会为假。

这似乎表明我需要等待其他一些事情以确保真正发出请求:此外,执行上述代码的线程在发出请求时仍然具有某种作用-断点。

也许,您想重用请求对象(我对此做了一些实验)。对我来说,我将请求对象保存在内存中,直到响应到达。无法保证在创建调用后不需要请求对象。


推荐阅读