技术文章 > 服务端 > pomelo 使用教程 > protobuf 压缩 

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 的数据通信格式。

小结

到这里为止,我们已经实现了一个功能基本完善的聊天应用了,我们使用了 pomelo 提供的 filter 机制,基于 dict 的 route 压缩和基于 protobuf 的消息压缩。下面将给聊天应用增加一些纯属“画蛇添足”的一些功能,目的是为了继续展示 pomelo 的特性。下一步,给聊天应用增加一个 rpc 调用


来源:摘自 https://github.com/NetEase/pomelo/wiki/protobuf%E5%8E%8B%E7%BC%A9,本站 行痴 整理