Protobuf 压缩
上面我们使用了 dictionary 的方式对聊天应用中的路由信息进行了压缩,减少了很多通信中的额外开销。在这里,我们将使用 pomelo 提供的 protobuf 实现完成通信消息的基于 protobuf 的压缩。
protobuf 是 google 提出的数据交换格式,关于 protobuf 的更多信息请参阅这里。
原始的 protobuf,首先需要定义一个 .proto 文件,然后调用 protoc 进行编译,根据不同的宿主语言,生成源码,然后将生成的源码应用到具体使用 protobuf 的应用中。这种使用方式比较笨重,因为涉及到了静态编译,应用程序无法在运行时动态地使用,一旦数据格式有变,就需要修改 proto,编译,重新生成源码。
pomelo 的 protobuf 实现,借助了 javascript 的动态性,使得应用程序可以在运行时解析 proto 文件,不需要进行 proto 文件的编译。pomelo 的实现中,为了更方便地解析 proto 文件,使用了 json 格式,与原生的 proto 文件语法是相通的,但不相同。用户定义好客户端以及服务端的通信所需要的信息格式的 proto 文件,服务端的 proto 配置放在 config/serverProtos.json 中,客户端的 proto 配置放在 config/clientProtos.json。如果在其配置文件里,配置了所有类型的 proto 信息,那么在通信过程中,将会全部使用二进制的方式对消息进行编码;如果没有定义某一类消息相应的 proto,pomelo 还是会使用初始的 json 格式对消息进行编码。
Chat 中使用
下面将 pomelo-protobuf 应用到我们的聊天应用中,具体的代码在分支 tutorial-protobuf 中,使用下面命令切换分支:$ git checkout tutorial-protobuf
首先提取所有的数据格式,分为客户端使用的数据格式以及服务器端使用的数据格式,如下:
// clientProtos.json
{
"chat.chatHandler.send": {
"required string rid": 1,
"required string content": 2,
"required string from": 3,
"required string target": 4
},
"connector.entryHandler.enter": {
"required string username": 1,
"required string rid": 2
},
"gate.gateHandler.queryEntry": {
"required string uid": 1
}
}
// serverProtos.json
{
"onChat": {
"required string msg": 1,
"required string from": 2,
"required string target": 3
},
"onLeave": {
"required string user": 1
},
"onAdd": {
"required string user": 1
}
}
然后将这两个配置文件分别命名为 clientProtos.json 和 serverProtos.json 中,并将这两个配置文件都放到 config 目录下;在我们的程序中开启 protobuf,在 app.js 的配置中,增加 protobuf 使用,在配置 connector 的时候,加入 useProtobuf:
app.configure('production|development', 'connector', function() {
app.set('connectorConfig', {
connector: pomelo.connectors.hybridconnector,
heartbeat: 3,
useDict: true,
useProtobuf: true //enable useProtobuf
});
});
app.configure('production|development', 'gate', function(){
app.set('connectorConfig', {
connector : pomelo.connectors.hybridconnector,
useDict: true,
useProtobuf: true //enable useProtobuf
});
});
这样,我们对我们的聊天应用进行了 protobuf 的压缩。当然,我们这里仅仅是为了示例,实际上,对于 onAdd 以及 onLeave 这样的,数据包本身就很小,而且又是字符串,对其使用 proto 压缩的效果不大,完全没必要进行使用 proto 压缩,而且使用 protobuf 压缩会造成编解码的效率开销,得不偿失。实际运用中,还是需要根据实际情况进行合理的选择,更多时候我们是在消息的压缩率和编解码的开销中达到一个平衡。对于 proto 文件里面没有配置的通信数据类型,pomelo 依然会使用原始的基于 json 的数据通信格式。