gRPC官方文档(异步基础: C++)
文章来自gRPC 官方文档中文版
异步基础: C++
本教程介绍如何使用 C++ 的 gRPC 异步/非阻塞 API 去实现简单的服务器和客户端。假设你已经熟悉实现同步 gRPC 代码,如gRPC 基础: C++所描述的。本教程中的例子基本来自我们在overview中使用的Greeter 例子。你可以在 grpc/examples/cpp/helloworld找到安装指南。
概览
gRPC 的异步操作使用CompletionQueue。 基本工作流如下:
- 在 RPC 调用上绑定一个
CompletionQueue - 做一些事情如读取或者写入,以唯一的
voide*标签展示 - 调用
CompletionQueue::Next去等待操作结束。如果标签出现,表示对应的操作已经完成。
异步客户端
要使用一个异步的客户端调用远程方法,你首先得创建一个频道和存根,如你在同步客户端中所作的那样。一旦有了存根,你就可以通过下面的方式来做异步调用:
初始化 RPC 并为之创建句柄。将 RPC 绑定到一个
CompletionQueue。CompletionQueue cq;
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
stub_->AsyncSayHello(&context, request, &cq));用一个唯一的标签,寻求回答和最终的状态
Status status;
rpc->Finish(&reply, &status, (void*)1);等待完成队列返回下一个标签。当标签被传入对应的
Finish()调用时,回答和状态就可以被返回了。void* got_tag;
bool ok = false;
cq.Next(&got_tag, &ok);
if (ok && got_tag == (void*)1) {
// check reply and status
}
你可以在这里greeter_async_client.cc看到完整的客户端例子。
异步服务器
服务器实现请求一个带有标签的 RPC 调用,然后等待完成队列返回标签。异步处理 RPC 的基本工作流如下:
构建一个服务器导出异步服务
helloworld::Greeter::AsyncService service;
ServerBuilder builder;
builder.AddListeningPort("0.0.0.0:50051", InsecureServerCredentials());
builder.RegisterAsyncService(&service);
auto cq = builder.AddCompletionQueue();
auto server = builder.BuildAndStart();请求一个 RPC 提供唯一的标签
ServerContext context;
HelloRequest request;
ServerAsyncResponseWriter<HelloReply> responder;
service.RequestSayHello(&context, &request, &responder, &cq, &cq, (void*)1);等待完成队列返回标签。当取到标签时,上下文,请求和应答器都已经准备就绪。
HelloReply reply;
Status status;
void* got_tag;
bool ok = false;
cq.Next(&got_tag, &ok);
if (ok && got_tag == (void*)1) {
// set reply and status
responder.Finish(reply, status, (void*)2);
}等待完成队列返回标签。标签返回时 RPC 结束。
void* got_tag;
bool ok = false;
cq.Next(&got_tag, &ok);
if (ok && got_tag == (void*)2) {
// clean up
}
然而,这个基本的工作流没有考虑服务器并发处理多个请求。要解决这个问题,我们的完成异步服务器例子使用了 CallData 对象去维护每个 RPC 的状态,并且使用这个对象的地址作为调用的唯一标签。
class CallData {
public:
// Take in the "service" instance (in this case representing an asynchronous
// server) and the completion queue "cq" used for asynchronous communication
// with the gRPC runtime.
CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq)
: service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) {
// Invoke the serving logic right away.
Proceed();
}
void Proceed() {
if (status_ == CREATE) {
// As part of the initial CREATE state, we *request* that the system
// start processing SayHello requests. In this request, "this" acts are
// the tag uniquely identifying the request (so that different CallData
// instances can serve different requests concurrently), in this case
// the memory address of this CallData instance.
service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_,
this);
// Make this instance progress to the PROCESS state.
status_ = PROCESS;
} else if (status_ == PROCESS) {
// Spawn a new CallData instance to serve new clients while we process
// the one for this CallData. The instance will deallocate itself as
// part of its FINISH state.
new CallData(service_, cq_);
// The actual processing.
std::string prefix("Hello ");
reply_.set_message(prefix + request_.name());
// And we are done! Let the gRPC runtime know we've finished, using the
// memory address of this instance as the uniquely identifying tag for
// the event.
responder_.Finish(reply_, Status::OK, this);
status_ = FINISH;
} else {
GPR_ASSERT(status_ == FINISH);
// Once in the FINISH state, deallocate ourselves (CallData).
delete this;
}
}
简单起见,服务器对于所有的事件只使用了一个完成队列,并且在 HandleRpcs 中运行了一个主循环去查询队列:
void HandleRpcs() {
// Spawn a new CallData instance to serve new clients.
new CallData(&service_, cq_.get());
void* tag; // uniquely identifies a request.
bool ok;
while (true) {
// Block waiting to read the next event from the completion queue. The
// event is uniquely identified by its tag, which in this case is the
// memory address of a CallData instance.
cq_->Next(&tag, &ok);
GPR_ASSERT(ok);
static_cast<CallData*>(tag)->Proceed();
}
}
你可以在greeter_async_server.cc看到完整的服务器例子。
gRPC官方文档(异步基础: C++)的更多相关文章
- gRPC官方文档(gRPC基础:C++)
文章来自gRPC 官方文档中文版 本教程提供了C++程序员如何使用gRPC的指南. 通过学习教程中例子,你可以学会如何: 在一个 .proto 文件内定义服务. 用 protocol buffer 编 ...
- gRPC官方文档(概览)
文章来自gRPC 官方文档中文版 概览 开始 欢迎进入 gRPC 的开发文档,gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 本文档通过快速概述和 ...
- gRPC官方文档(概念)
文章来自gRPC 官方文档中文版 gRPC 概念 本文档通过对于 gRPC 的架构和 RPC 生命周期的概览来介绍 gRPC 的主要概念.本文是在假设你已经读过文档部分的前提下展开的.针对具体语言细节 ...
- gRPC官方文档(安全认证)
文章来自gRPC 官方文档中文版 认证 gRPC 被设计成可以利用插件的形式支持多种授权机制.本文档对多种支持的授权机制提供了一个概览,并且用例子来论述对应API,最后就其扩展性作了讨论. 马上将会推 ...
- gRPC官方文档(通讯协议)
文章来自gRPC 官方文档中文版 HTTP2 协议上的 gRPC 本文档作为 gRPC 在 HTTP2 草案17框架上的实现的详细描述,假设你已经熟悉 HTTP2 的规范.产品规则采用的是ABNF 语 ...
- NHibernate官方文档中文版--基础ORM(Basic O/R Mapping)
映射声明 对象/关系映射在XML文件中配置.mapping文件这样设计是为了使它可读性强并且可修改.mapping语言是以对象为中心,意味着mapping是围绕着持久化类声明来建立的,而不是围绕数据表 ...
- Android 触摸手势基础 官方文档概览
Android 触摸手势基础 官方文档概览 触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: Moti ...
- Android 触摸手势基础 官方文档概览2
Android 触摸手势基础 官方文档概览 触摸手势检测基础 手势检测一般包含两个阶段: 1.获取touch事件数据 2.解析这些数据,看它们是否满足你的应用所支持的某种手势. 相关API: Moti ...
- log4j2异步日志配置及官方文档的问题澄清
配置及demo 方法一全部打开 加启动参数 -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextS ...
随机推荐
- Win10 Bash更改默认用户
Win10已经支持Ubuntu的Bash了. 在cmd中输入bash就可以进入bash界面.但此时是普通用户登录的. 如果希望更改默认的登录用户,可以在cmd中更改. 具体的命令是: lxrun /s ...
- L2-014. 列车调度(set的使用,最长递增子序列)
L2-014. 列车调度 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 火车站的列车调度铁轨的结构如下图所示. Figure ...
- Eclipse中的普通Java项目如何部署到Tomcat中
我现在的做法: 1.在Eclipse中配置Tomcat时,选择创建Context文件,而不是server.xml,好处是文件可以随便命名,与虚拟目录一致(即xml中的属性path).Tomcat加载项 ...
- 用IntelliJ IDEA建maven项目,如何解决main下无法创建java源文件
一.缺少java源文件 如下图: 现在想要在main下面增加java源文件,效果图如下所示: 首先,在main目录下新建java文件夹,就是源文件目录, 然后,右键,选择Mark Directory ...
- LNMP 1.2 Nginx编译安装
Nginx官网是:nginx.org 下载稳定版本 cd /usr/local/src wget http://nginx.org/download/nginx-1.8.0.tar.gz tar zx ...
- DAY11-MYSQL索引原理与慢查询优化
一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
- 用JS实现,图片放大和缩小
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Eclipse 快键键(持续更新)
本人抛弃一些简单常见的快键键,例如 ctrl+c ,+v ,+z之类的 1.ctrl+d 删除一整行 2.ctrl+f 搜索 3.光标选中几行,ctrl+alt+↓ 向下复制选中的那几行 4.光标 ...
- 第5章 使用MUI与H5+构建移动端app
H5+是JS封装的工具集合,通过H5+我们就可以使用JS的方式去调用到我们手机端上的一些原生的组件. http://dev.dcloud.net.cn/mui/ http://dev.dcloud.n ...
- [poj1509]Glass Beads(最小表示法)
题目大意:求循环同构的字符串的最小字典序. 解题关键:最小表示法模板题. #include<cstdio> #include<cstring> #include<algo ...