什么样的RPC才是好用的RPC
现在RPC框架很多,但是真正好用的RPC却是少之又少。那么什么是好用的RPC,什么是不好用的RPC呢,有一个评判标准吗?下面是我列举出来的衡量RPC好用与否的几条标准:
- 真的像本地函数一样调用
- 使用简单,用户只需要关注业务即可
- 灵活,RPC调用的序列化方式可以自由定制,比如支持json,支持msgpack等方式
下面来分别解释这几条标准。
标准1:真的像本地函数一样调用
RPC的本质是为了屏蔽网络的细节和复杂性,提供易用的api,让用户就像调用本地函数一样实现远程调用,所以RPC最重要的就是“像调用本地函数一样”实现远程调用,完全不让用户感知到底层的网络。真正好用的RPC接口,他的调用形式是和本地函数无差别的,但是本地函数调用是灵活多变的。服务器如果提供和客户端完全一致的调用形式将是非常好用的,这也是RPC框架的一个巨大挑战
标准2:使用简单,用户只需要关注业务即可
RPC的使用简单直接,非常自然,就是和调用本地函数一样,不需要写一大堆额外代码,用户只用写业务逻辑代码,而不用关注框架的细节,其他的事情都由RPC框架完成。
标准3:灵活,RPC调用的序列化方式可以自由定制
RPC调用的数据格式支持多种编解码方式,比如一些通用的json格式、msgpack格式或者boost.serialization等格式,甚至支持用户自己定义的格式,这样使用起来才会更灵活。
RPC框架评估
下面根据这几个标准来评估一些国内外知名大公司的RPC框架,这些框架的用法在github的wiki中都有使用示例,使用示例代码均来自官方提供的例子。
谷歌gRPC
gRPC最近发布了1.0版本,他是谷歌公司用c++开发的一个RPC框架,并提供了多种客户端。
协议定义
先定义一个.proto的文件,例如 // Obtains the feature at a given position. rpc GetFeature(Point) returns (Feature) {} 定义了一个服务接口,接收客户端传过来的Point,返回一个Feature,接下来定义protocol buffer的消息类型,用于序列化/反序列化 message Point { int32 latitude = 1; int32 longitude = 2; }
服务器代码
class RouteGuideImpl final : public RouteGuide::Service { Status GetFeature(ServerContext* context, const Point* point, Feature* feature) override { feature->set_name(GetFeatureName(*point, feature_list_)); feature->mutable_location()->CopyFrom(*point); return Status::OK; } } void RunServer(const std::string& db_path) { std::string server_address("0.0.0.0:50051"); RouteGuideImpl service(db_path); ServerBuild