<< std::endl; return false; } return true;}評價
gRPC調(diào)用的序列化用的是protocal buffer,,RPC服務(wù)接口需要在.proto文件中定義,,使用稍顯繁瑣。根據(jù)標準1,,gRPC并沒有完全實現(xiàn)像本地調(diào)用一樣,,雖然很接近了,但做不到,,原因是RPC接口中必須帶一個Context的參數(shù),,并且返回類型必須是Status,這些限制導致gRPC無法做到像本地接口一樣調(diào)用,。
根據(jù)標準2,,gRPC的使用不算簡單,需要關(guān)注諸多細節(jié),,比如Context和Status等框架的細節(jié),。根據(jù)標準3,gRPC只支持pb協(xié)議,,無法擴展支持其他協(xié)議,。
綜合評價:70分,。
百度sofa-pbRPC
sofa-pbRPC是百度用c++開發(fā)的一個RPC框架,和gRPC有點類似,,也是基于protocal buffer的,,需要定義協(xié)議。
協(xié)議定義
// 定義請求消息
message EchoRequest {
required string message = 1;
}
// 定義回應(yīng)消息message EchoResponse { required string message = 1;}// 定義RPC服務(wù),,可包含多個方法(這里只列出一個)service EchoServer { rpc Echo(EchoRequest) returns(EchoResponse);}
服務(wù)器端代碼
#include // sofa-pbrpc頭文件#include 'echo_service.pb.h' // service接口定義頭文件class EchoServerImpl : public sofa::pbrpc::test::EchoServer{public: EchoServerImpl() {} virtual ~EchoServerImpl() {}private: virtual void Echo(google::protobuf::RpcController* controller, const sofa::pbrpc::test::EchoRequest* request, sofa::pbrpc::test::EchoResponse* response, google::protobuf::Closure* done) { sofa::pbrpc::RpcController* cntl = static_cast<sofa::pbrpc::RpcController*>(controller); SLOG(NOTICE, 'Echo(): request message from %s: %s', cntl->RemoteAddress().c_str(), request->message().c_str()); response->set_message('echo message: ' + request->message()); done->Run(); }};注意:服務(wù)完成后必須調(diào)用done->Run(),,通知RPC系統(tǒng)服務(wù)完成,觸發(fā)發(fā)送Response,;在調(diào)了done->Run()之后,,Echo的所有四個參數(shù)都不再能訪問;done-Run()可以分派到其他線程中執(zhí)行,,以實現(xiàn)了真正的異步處理,;
客戶端代碼
int main(){ SOFA_PBRPC_SET_LOG_LEVEL(NOTICE); // 定義RpcClient對象,管理RPC的所有資源 // 通常來說,,一個client程序只需要一個RpcClient實例 // 可以通過RpcClientOptions指定一些配置參數(shù),,譬如線程數(shù)、流控等 sofa::pbrpc::RpcClientOptions client_options; client_options.work_thread_num = 8; sofa::pbrpc::RpcClient rpc_client(client_options); // 定義RpcChannel對象,,代表一個消息通道,,需傳入Server端服務(wù)地址 sofa::pbrpc::RpcChannel rpc_channel(&rpc_client, '127.0.0.1:12321'); // 定義EchoServer服務(wù)的樁對象EchoServer_Stub,使用上面定義的消息通道傳輸數(shù)據(jù) sofa::pbrpc::test::EchoServer_Stub stub(&rpc_channel); // 定義和填充調(diào)用方法的請求消息 sofa::pbrpc::test::EchoRequest request; request.set_message('Hello world!'); // 定義方法的回應(yīng)消息,,會在調(diào)用返回后被填充 sofa::pbrpc::test::EchoResponse response; // 定義RpcController對象,,用于控制本次調(diào)用 // 可以設(shè)置超時時間、壓縮方式等,;默認超時時間為10秒,,默認壓縮方式為無壓縮 sofa::pbrpc::RpcController controller; controller.SetTimeout(3000); // 發(fā)起調(diào)用,最后一個參數(shù)為NULL表示為同步調(diào)用 stub.Echo(&controller, &request, &response, NULL); // 調(diào)用完成后,,檢查是否失敗 if (controller.Failed()) { // 調(diào)用失敗后的錯誤處理,,譬如可以進行重試 SLOG(ERROR, 'request failed: %s', controller.ErrorText().c_str()); } return EXIT_SUCCESS;}
評價
sofa-pbRPC的使用并沒有像sofa這個名字那樣sofa,根據(jù)標準1,,服務(wù)端的RPC接口比gRPC更加復(fù)雜,,更加遠離本地調(diào)用了。根據(jù)標準2,,用戶要做很多額外的事,,需要關(guān)注框架的很多細節(jié),比較難用,。根據(jù)標準3,同樣只支持pb協(xié)議,,無法支持其他協(xié)議,。
綜合評價:62分,。
騰訊Pebble
騰訊開源的Pebble也是基于protocal buffer的,不過他的用法比gRPC和sofaRPC更好用,,思路都是類似的,,先定義協(xié)議。
協(xié)議定義
struct HeartBeatInfo { 1: i64 id, 2: i32 version = 1, 3: string address, 4: optional string comment,}service BaseService { i64 heartbeat(1:i64 id, 2:HeartBeatInfo data), oneway void log(1: string content)}
服務(wù)器端代碼
class BaseServiceHandler : public BaseServiceCobSvIf {public: void log(const std::string& content) { std::cout << 'receive request : log(' << content << ')' << std::endl; }};int main(int argc, char* argv[]) { // 初始化RPC pebble::rpc::Rpc* rpc = pebble::rpc::Rpc::Instance(); rpc->Init('', 0, ''); // 注冊服務(wù) BaseServiceHandler base_service; rpc->RegisterService(&base_service); // 配置服務(wù)監(jiān)聽地址 std::string listen_addr('tcp://127.0.0.1:'); if (argc > 1) { listen_addr.append(argv[1]); } else { listen_addr.append('8200'); } // 添加服務(wù)監(jiān)聽地址 rpc->AddServiceManner(listen_addr, pebble::rpc::PROTOCOL_BINARY); // 啟動server rpc->Serve(); return 0;}
客戶端代碼
// 初始化RPCpebble::rpc::Rpc* rpc = pebble::rpc::Rpc::Instance();rpc->Init('', -1, '');// 創(chuàng)建rpc client stubBaseServiceClient client(service_url, pebble::rpc::PROTOCOL_BINARY);// 同步調(diào)用int ret = client.log('pebble simple test : log');std::cout << 'sync call, ret = ' << ret << std::endl;
評價
Pebble比gRPC和sofa-pbrpc更好用,,根據(jù)標準1,,調(diào)用方式和本地調(diào)用一致了,接口中沒有任何限制,。根據(jù)標準2,,除了定義協(xié)議稍顯繁瑣之外已經(jīng)比較易用了,不過服務(wù)器在使用上還是有一些限制,,比如注冊服務(wù)的時候只能注冊一個類對象的指針,,不能支持lambda表達式,std::function或者普通的function,。根據(jù)標準3,,gRPC只支持pb協(xié)議,無法擴展支持其他協(xié)議,。
綜合評價:75分,。
apache msgpack-RPC
, 1, 2).get<int>(); std::cout << result << std::endl;}評價
msgpack-RPC使用起來也很簡單,不需要定義proto文件,,根據(jù)標準1,,客戶端的調(diào)用和本地調(diào)用一致,不過,,服務(wù)器的RPC接口有一個msgpack::rpc::request對象,,并且也必須派生于base類,使用上有一定的限制,。根據(jù)標準2,,服務(wù)器端提供RPC服務(wù)的時候需要根據(jù)method的名字來dispatch,這種方式不符合開閉原則,,使用起來有些不方便,。根據(jù)標準3,msgpack-rpc只支持msgpack的序列化,,不能支持其他的序列化方式,。
綜合評價:80分。
總結(jié)
目前雖然國內(nèi)外各大公司都推出了自己的RPC框架,,但是真正好用易用的RPC框架卻是不多的,,這里對各個廠商的RPC框架僅從好用的角度做一個評價,一家之言,,僅供參考,,希望可以為大家做RPC的技術(shù)選型的時候提供一些評判依據(jù),。
轉(zhuǎn)自:CSDN博客 作者:qicosmos