关于msg id的思考

来源:互联网 发布:怎么看手机的mac地址 编辑:程序博客网 时间:2024/06/04 19:48

 1 应用场景


       在经典的c/s模型中,客户端与服务端之间的通信消息类型通常不只一种,为了标识不同的消息类型,以对不同的消息做出恰当的处理,才在应用层有了msg id,即便是rpc机制,本质上也是将函数名当作msg id,msg id不得不存在的本质原因是tcp/ip只管网络传输,至于传输了什么内容,完全没有办法识别,只能靠应用层去检测


  2  msg id如何设计


       这或许是最简单的问题了,只要能保证每个消息类型都能分配到唯一的id就ok了,如果是这样的话,一个整型数字就完美解决了,假设项目无止尽的发展下去,功能越来越复杂,系统模块越来越多,那么维护这样一个整型数字会不会给程序员带来不必要的负担?为了更好的描述这个问题的真实存在性,假设以下这几个例子。

        a. 项目的初期,只有很少的一部分功能,也许就只有一个模块,命名为module1,msg id也被定义为从1-n(n很小,维护这个完全不存在任何问题),好,demo让人满意,继续扩展,增加了module2,3,4....module2的msg id从n+1开始,module3,4..以此类推,项目的中期,突然有个需求,要增加module1的功能,之前已经定义好的消息码是不可能去改动了,因为如果要改动,可能意味着整个要重新编译打包发布,还要面临部分客户端就是不更新导致消处码不兼容问题,所以改动此前已定义好的消息码尽量不要出现在发布后,既然已有的没法改动,考虑兼容的问题,只好将module1的新功能的msg id放在modulen的后面,项目继续发展,增加功能这种事情,几乎每个module都发生了几遍(好像有点极端了),msg id的定义文件一眼望去,毫无规律,要从一堆的msg id找到自己想要的,要么记性好,要么眼力好,因为有多个程序员同时开发不同的功能,有好几次因为msg id定义冲突,发生了些不愉快的事情

       b. 项目的初期,就对msg id有规划,每个功能模块只能分配固定N个id,用不完的就预留,通常这个N足够一个功能模块使用,一开始就定好不同功能模块的msg id段,一切都变的美好起来。随着项目的逐渐发展,居然把msg id用完了(极端例子,假设msg id用的是16位整数,出于节省带宽的考虑),原因是功能模块太多,而为每个功能模块预留的N个消息码大部分都被浪费了,项目还得继续,将msg id变为32位或者更大,会出现服务端与客户端消息不兼容的情况,还有新的功能模块要增加,看来得重走a的路了,但还是要比a好一些

       c. 将msg id定义为多个层级,有module msg id, sub msg id...,最顶层的是模块id,消息转发时,会先根据模块id转发到对应的模块上,不同的模块,又根据sub msg id再次转发,以此类推,最顶层只要先定义好各自的模块id,模块内部,通常只有一个程序在维护,sub msg id与其他功能模块是完全隔离了,不可能再有冲突了,也变的好维护了,新增模块也好,已有模块升级也好,都没有任何问题,只是这被一部分程序员认为是复杂的设计,因为新增的功能模块,可能只有一两个消息码,而要新增一个功能模块时,要添加模块id,要处理模块id对应的消息转发,然后才到真正最重要的业务逻辑处理,走了些弯路,不够直接

        d. 采用rpc机制,msg id 被隐式的转成了远程函数名,对于程序员来说,msg id就此消失,不过一个完备的rpc框架,本身就有一定的复杂度,另一方面,rpc与前面的通过msg id来分发消息的机制,通常会并存(项目实际复杂的情况所决定的),但rpc框架绝对是值的提倡的一种机制,至少在分布式中,服务器之间的通讯采用rpc机制的话,会大大减小项目开发成本(其他的应用场景没研究过)


3  题外话


       实际的敲代码经历中,一个看似简单的东西,也需要经过一定的思考之后才能决定最终的实现,除非之前有应对过类似问题的经验。涉及到代码管理,多人共同维护时,凡是存在共享的资源时,就像多线程的竞态条件般,需要考虑资源分配的问题,这时不妨让自己当一回操作系统,让资源分配尽可能合理,尽可能减少共同使用资源时所带来的成本。

       代码狗的生活状况比较惨,本想将lua虚拟机的分析一直写下去,但却一直被赶进度,而且目前的项目也没有用到lua,除了少数几个我写的工具外(个人偏爱lua),争取下一个项目说服工头使用lua吧,那时,再结合实际的项目再来谈谈lua


0 0