標籤:

基於 Coroutine 的非同步 RPC 框架示例(C++)

最近看了 gRPC C++ 實現的非同步介面,感覺實在是不友好,尤其是 Server 端。具體可見 greeter_async_client.cc,greeter_async_server.cc。

這裡秀一下我司的非同步 RPC 框架,同樣是基於 Protobuf,但我們基於 Coroutine 實現用同步的方式寫非同步程序。

Client 端示例如下:

Status RunClient(const std::string& ip, int port, uint64_t num_client, uint64_t round) { EventLoop loop; uint64_t undone = num_client; LOOP(num_client) { auto co = Coroutine::Create([&]() { Client client(ip, port, &loop); EchoService::Stub service(&client); ASSERT_STATUS(client.ConnectRemote()); LOOP(round) { Controller ctrl; EchoRequest request; EchoResponse response; request.set_msg(RandString()); service.Echo(&ctrl, &request, &response, nullptr); ASSERT_TRUE(!ctrl.Failed()); ASSERT_EQ(response.msg(), request.msg()); } undone--; }); co->Enter(); } while (undone) { loop.LoopOnce(); } return Status::OK;}

這段代碼模擬了多個 rpc client 並發向 rpc server 發送請求。

Server 端示例如下:

class EchoServiceImpl : public EchoService { public: void Echo(RpcController* ctrl, const EchoRequest* request, EchoResponse* response, Closure* done) { response->set_msg(request->msg()); done->Run(); }};Status RunServer(const std::string& ip, int port) { EventLoop loop; RpcServer server(ip, port, &loop); EchoServiceImpl impl; server.RegisterService(&impl); RETURN_IF_ERROR(server.Start()); loop.Loop(); return Status::OK;}

除了非同步 RPC 以外,磁碟 IO 也可以通過 Coroutine 進行封裝。

其實從實現上來說,通過 Coroutine 封裝非同步操作並沒有太大的難度,但帶來的好處是巨大的。這裡鼓勵大家多去嘗試。

作者介紹

@張凱(Kyle Zhang) ,SmartX 聯合創始人 & CTO。SmartX 擁有國內最頂尖的分散式存儲和超融合架構研發團隊,是國內超融合領域的技術領導者。


推薦閱讀:

關於go語言協程調度的一個問題(具體請看問題描述)?
「遊戲引擎Mojoc」(7)C使用goto label地址實現協程
Unity 協程運行時的監控和優化
考不上三本也能給自己心愛的語言加上Coroutine(一)
開源一個超簡單的無棧協程原型(5)

TAG:Linux | C | 协程 |