MESSAGE-PACK-RPC¶
- 起始时间:2018-1-22
- 版本:0.1
- 作者:hsz
概述¶
MESSAGE-PACK-RPC是一个轻量级的无状态远程过程调用(RPC)应用层协议.它参考自JSON-RPC 2.0协议, 但它是独立的也不向JSON-RPC协议兼容.
本规范主要定义了一些数据结构及其相关的处理规则.它允许运行在基于tcp协议的消息传输环境中, 使用messagepack作为序列化和反序列化数据格式进行通信.
与json-rpc不同,message-pack-rpc的个请求形式可以有
- 应答模式,一问一答. 类似函数调用
- 服务端在获取请求后向客户端进行推送. 类似于调用一个生成器
注意流操作依然是使用的一般的应答,而非流式服务器.
其他的特性包括:
- 服务器端对连接建立的客户端可以有权限检验,也就是说可以设定口令
- 客户端主动关闭连接,服务端可以设置过期时间主动断开连接,默认为180秒.
- 允许设置客户端类型检查默认为True
- 允许客户端设定心跳以维持连接不会过期断开.默认为False
- 支持使用json替代message-pack,该模式为DEBUG模式,默认不使用DEBUG模式
- 可以在通信中进行使用
bz2
或者zlib
或者lzma
进行数据压缩. - 请求可以设置Return字段,默认为True,表示要求返回响应为结果,如果设置为False,则不必返回任何结果,而是通过方法
system.getresult
获取结果
流程约定¶
连接建立¶
连接建立后无论是否有验证需求,客户端都会向服务器发送一条验证请求,
- 如果服务端有验证信息,则会根据验证信息判断是否合法
- 如果合法,那么返回一条信息用于响应验证请求
- 如果不合法,那么返回验证错误
- 如果服务端没有验证信息
- 如果验证信息都为空,直接返回响应
- 如果信息不为空,那么返回验证错误
如果验证未通过,客户端会抛出验证错误异常,如果验证通过了就可以继续发送其他请求
发送调用请求¶
验证请求通过后客户端才可以发送调用请求,请求接收后会检测
- 函数是否被注册存在
- 函数的参数是否与签名匹配
执行成功后会返回结果,失败则返回错误.而客户端收到结果后进行解析,如果是错误则解析出来抛出对应的错误
关闭连接¶
关闭连接有两种情况
客户端主动关闭连接
客户端应该在请求完毕后主动关闭连接.这并不需要额外的请求,直接关闭即可,服务器端收到EOF标识后会自动清理这个连接
连接过期服务器关闭连接
服务器每次写操作都会更新一个最近响应时间,如果长时间没有响应时间,则连接过期,服务器端主动关闭这个连接并向客户端发送一个超时错误.客户端收到超时错误消息后会抛出对应错误.默认的超时时间为180s
如果想要一直保持连接,则需要客户端每隔一段时间发送一个心跳’ping’给服务器,服务器会响应’pong’同时刷新最近响应时间来避免超时.
数据形式约定¶
所有的出传输都以长连接的形式构建,没条请求以b##PRO-END##
作为终止符
数据形式约定分为如下几个层次:
- 传输数据类型和关键字格式约定
JSON可以表示四个基本类型(String、Numbers、Booleans和Null)和两个结构化类型(Objects和Arrays).而我们的message-pack也是以这6种基本类型为基础.
我们规定rpc注册的函数的参数和返回值也只能在这6种类型.且要求参数和返回值中的Object不允许嵌套
同时规定必须使用英文大写单词标识协议用到的字段,而协议预设的函数名也必须是大写.
可以用于传输的对象约定
我们约定合法的对象包括:
- 验证请求对象
- 自描述应答对象
- 心跳请求与应答对象
- 函数调用请求和响应对象
- 异常/错误对象
- 结果对象
连接建立时客户端发送验证信息.
成功建立连接后客户端会向服务发送一个验证请求,其形式为:
{ "MPRPC":"0.1",// string 协议版本号 "AUTH":{ "USERNAME":xxx,//string "PASSWORD":xxx//string } }
连接建立时服务端的自描述应答格式约定
成功建立连接后服务器会收到验证请求,如果请求通过则会返回一个message-pack字节序列指明本rpc的基本信息,其形式为:
{ "MPRPC":"0.1",// string 协议版本号 "CODE":100,//指示允许访问 "VERSION":"0.0.1",//string 服务的版本用于在客户端检验 "DESC":"xxxx",// string 描述服务 "DEBUG":true,// bool 是否使用debug模式,也就是传递的是json还是msgpack "COMPRESER":null,// enum 压缩算法,可选的有`bz2`,`zlib`,`lzma`和null "TIMEOUT":180,//number 设置的过期时间,设为0表示不设置过期时间 }
验证失败的话则会返回
{ "MPRPC":"0.1",// string 协议版本号 "CODE":501 }
客户端接收到错误后的行为
客户端接收到错误后会先关闭连接然后抛出对应异常
由客户端关闭连接后服务端的行为
客户端关闭连接属于正常行为,没有额外动作
心跳请求对象约定
{ "MPRPC":"0.1",// string 协议版本号 "HEARTBEAT":"ping" }
心跳请求对象约定
{ "MPRPC":"0.1",// string 协议版本号 "CODE":101, "HEARTBEAT":"pong" }
请求对象约定
{ "MPRPC":"0.1",// string 协议版本号 "ID":xxxx,//string 任务id "METHOD": xxx,//接收到要执行的函数名 "RETURN":True,//默认为True,表示会返回结果,设置为False则表示不用返回结果,要结果的话可以用system.getresult获取 "ARGS":xxx //(OPTION) list 接收到函数调用的参数,只允许为列表形式,如果有stream则无效 "KWARGS":xxx //(OPTION) dict 接收到函数调用的参数,键值对的形式,如果有stream则无效 }
响应对象约定
当发起一个rpc调用时,除通知之外,服务端都必须回复响应。响应表示为一个JSON对象,使用以下成员:
{ "MPRPC":"0.1",// str 协议版本号 "CODE":200,// number 响应码,响应码反应服务器状态, "MESSAGE": {} //(OPTION) object 对象为结果对象或者异常/错误对象 }
响应码含义表(参考自http协议)
- 服务器回应,表述状态
code|对应错误|意义 —|—|– 100|—|表示初始的请求已经接受,客户应当继续发送请求的其余部分. 101|—|表示响应为一个心跳
- 正常响应
code|对应错误|意义 —|—|– 200|—|表示执行正常,返回的结果结束 201|—|表示已经接受请求,且返回为一个流 202|—|表示返回一个流的内容 206|—|返回的流结束了
- 过期警告
code|对应错误|意义 —|—|– 300|ExpireWarning|即将过期的函数执行正常 301|ExpireStreamWarning|即将过期的函数,表示已经接受请求,且返回为一个流
- method执行错误
code|对应错误|意义 —|—|– 400|RequestError|请求错误 401|NotFindError|未找到对应的函数 402|ParamError|请求的参数与签名不符 403|RestrictAccessError|限制访问对应函数 404|RPCRuntimeError|执行错误 405|ResultLimitError|返回的结果超过限制的字节限制 406|UnsupportSysMethodError|不支持的服务器固有方法
- 服务器异常
code|对应错误|意义 —|—|– 500|RpcException|服务器异常 501|LoginError|登录失败(口令有误) 502|RequirementException|服务器的依赖服务异常, 503|RpcUnavailableException|服务器不可用异常,一般是在维护 504|TimeoutException|服务器连接超时异常 505|ProtocolException|协议错误 506|ProtocolSyntaxException|协议语法错误
- 警告/错误异常对象约定
针对任务的错误
{ ID: xxx,// string 任务id EXCEPTION: xxx// string 服务器端错误/异常类型名 MESSAGE: xxxx,// string or array or object 错误描述文字 DATA: {//(OPTION) 错误的附加信息,由服务器决定,下面的是参考字段 METHOD: //(OPTION)接收到要执行的函数名 ARGS: //(OPTION)接收到函数调用的参数 FRAME: //(OPTION)错误的帧信息 } }
服务器发出的错误没有message,直接通过错误码识别
- 结果对象约定
{ ID: xxx,// string 任务id RESULT: xxx// any 返回的结果 }
服务器固有方法约定¶
system.listMethods()
返回对外的函数接口
system.methodSignature(method:str)->obj
返回指定函数的签名
system.methodHelp(method:str)->str
返回对外的函数接口
system.lenConnections()->int:
当前的连接总数
system.lenUndoneTasks()->int:
当前还未完成的任务数
system.getresult(ID:str)->Any:
获取某个ID对应的任务结果
客户端可设置参数:¶
- host 主机
- port 端口
- auth 验证信息,默认为None
- remote_version 远程服务的版本号,默认为None
- heart_beat 默认为False
服务器可设置参数:¶
- DEBUG 是否使用debug模式,默认为False
- AUTH 验证信息,默认为None
- COMPRESSION 使用什么进行压缩,默认为None
- VERSION 服务的版本用于在客户端检验默认为None
- DESC 描述服务的字符串,默认None,python实现可以直接返回对象的
__doc__
- TIMEOUT 多久没有请求就关闭连接默认为None
- MPRPC 协议版本号,默认为最新
负载均衡方案(未定义)¶
定义中介的交互数据形式(未定义)¶
身份验证(未定义)¶
使用与服务器一致的身份验证.
请求:
{
"MPRPC":"0.1",// str 协议版本号
"AUTH":{
"USERNAME":xxx,//string
"PASSWORD":xxx//string
}
}
失败响应:
{
"MPRPC":"0.1",// str 协议版本号
"CODE":51
}
成功响应:
{
"MPRPC":"0.1",// str 协议版本号
"CODE":50,
"URL":xxxxx
}
响应码含义表(参考自http协议)(未定义)¶
中介使用0~100间的状态码,其中0~50位请求码段,50~100为响应码段
code|对应错误|意义 —|—|– 50|—|验证通过 51|BrokerLoginError|验证失败