之前写过一篇 为什么 skynet 提供的包协议只用 2 个字节表示包长度 里面提到, 如果有体积很大的消息传递需求,那么应该在上一层去处理。
从另一方面来说,我们应该正视长消息的处理,而不应该将其和普通(较短)消息的处理混为一谈,在底层抹平之间的区别。
最近,需求就来了。
我们的一个新项目希望在 cluster 间通讯的时候,可以支持较大的消息。原本提出需求的同学想自己修改 skynet 的 cluster 模块,修改底层协议的包头长度的。我即使阻止了他,并自己动手做了修改。
简单说,就是在上一层的 cluster 协议上,增加了长消息的标识。由于之前就有一个字节做标识,其实并没有对协议做太大的修改。
当消息(无论是请求还是回应)太长时,就分开打包,并在标识字节上表明这只是一个完整消息的一部分。然后在接收方合并即可。
一开始我并不打算修改 cluster 依赖的socket channel 模块 ,让分开的每个小包都有一个独立的 session 。做了一半以后,发现对 socket channel 做一些增强(不应该之前的接口)会更好一些。而且可以很容易利用上之前做的 socket 低优先级队列这个特性。
新的修改我暂时提交到一个叫 multipart 的 skynet 独立分支上,欢迎感兴趣的同学 review 。
同时,我把 skynet 之前的两个含义不明确的内部宏重新定义了,去掉了之前对内部消息长度的 16M 限制。
经过一些简单测试,目前可以达到设计目标:在 cluster 内部,rpc 的请求和回应消息都不再受之前的 64K 限制。而且,一旦消息过长(目前是以 32k 为界),长消息的传输会被分成多个小于 32K 的消息投递,并且其它短消息允许穿插在其间。也就是说,如果你用 cluster 向外投递一个几十 M 的巨大消息的话,不会因为消息过大而阻塞了通讯通道。