基於 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)