您的位置:首页 > 编程语言 > Java开发

以小见大——那些基于 protobuf 的五花八门的 RPC(2)

2011-04-11 17:22 567 查看
赖勇浩(http://laiyonghao.com


多看了三五个 rpc 实现之后,这个事儿就变得很有趣了,今儿来看 fepss-rpc 和 casocklib,分别基于 java 和 C++ 开发。

fepss-rpc

它的简介是Protocol Buffers RPC Server Implemention based on Mina(2.0.0-RC1) and Protobuf(2.1.0),基本的包格式见:https://github.com/jcai/fepss-rpc/blob/master/src/main/resources/com/fepss/rpc/client/rpc.proto
,全文如下:
package com.fepss.rpc.client;
option java_package = "com.fepss.rpc.client";
option java_outer_classname = "RpcProtobuf";
option optimize_for = SPEED;
// Possible error reasons
enum ErrorReason {
BAD_REQUEST_DATA = 0;
BAD_REQUEST_PROTO = 1;
SERVICE_NOT_FOUND = 2;
METHOD_NOT_FOUND = 3;
RPC_ERROR = 4;
RPC_FAILED = 5;
CLIENT_FAILED=6;
}
message Request {
// RPC service full name
required string service_name = 1;

// RPC method name
required string method_name = 2;

// RPC request proto
required bytes request_proto = 3;
}
message Response {
// RPC response proto
optional bytes response_proto = 1;

// Eror, if any
optional string error = 2;

// Was callback invoked
optional bool callback = 3 [default = false];

// Error Reason
optional ErrorReason error_reason = 4;
}


可以看到 ErrorReason 定义了几个常见的错误:比如没有 Service,或有 Service 却没有相应的 method 等等,不过我对 BAD_REQUEST_DATA、BAD_REQUEST_PROTO、CLIENT_FAILED 表示不淡定,原因是对于前两者,我推崇发现非法协议就断开连接甚至采取更严厉的手段,而后者,客户端都出问题了,那 response 还能发送过去吗?

这个 Request 的设计比 protobuf-rpc 要好得多,因为它把 service_name 和 method_name 作为两个字段,非常明晰。但是它采用了无 id 设计,所以没有办法实现 Parallel Pipelining,肯定并发性能很差。关于 pp,我借用 msgpack-rpc 的一张图来说明一下:



而 Response 类的设计,我比较不明白 callback 的意图,还请读者中的行家赐教一二,多谢先。这里采用了 ErrorReason 和 error 分为两个字段的设计,我个人觉得有会让人有点小困惑,还不如 protobuf-rpc 的 Error 设计,通过 optional 实现 union。

casocklib

看完一个 python 的 rpc,一个 java 的 rpc,终于来了一个 C++ 的,先看它的简介:An asynchronous communication library for C++,而它基本包格式见:http://code.google.com/p/casocklib/source/browse/trunk/src/casock/rpc/protobuf/api/rpc.proto
,如下:
package casock.rpc.protobuf.api;
enum ResponseType {
RESPONSE_TYPE_OK = 1;
RESPONSE_TYPE_ERROR = 2;
};
message RpcRequest {
required uint32 id = 1;
required string operation = 2;
optional bytes request = 3;
}
message RpcResponse {
required uint32 id = 1;
required ResponseType type = 2;
optional bytes response = 3;
}


代码很短,采用了相当轻量级的设计。首先旗帜鲜明地声明了响应包的种类:成功以及失败,对于失败,并没有细分。RpcRequest.id 使用 32 位无符号整型,跟 protobuf-rpc 一样,不过这里的 operation 却跟后者的 method 不一样,operation 是货真价实的 MethodDescriptor.name,从代码(http://code.google.com/p/casocklib/source/browse/trunk/src/casock/rpc/protobuf/client/RPCRequestBuilder.cc#50
)可以证实。因为每一个 RpcRequest.operation 都不带 service name,所以使用 Casocklib 是无法将多个 service host 到同一个端口的。

RpcResponse 因为带了一个 ResponseType,所以可以知道 method 到底有没有执行成功,同理 response 就设计成 optional 了,因为执行错误就不需要返回 response 了呀。

===========

未完待续,明天讲一个重量级一点的,设计独特的,基于 c++ 的 rpc 实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息