系统结构的选择

最近在帮公司整理系统结构,原来的系统采用thrift消息打通各个节点“奇经八脉”,但是这种网状的系统结构维护起来非常复杂,虽然thrift是个好东西,但是梳理好系统的交互和关系比用什么工具更加重要。

首先,这里说的系统结构指的是系统的模块以及功能的划分,各个模块存在的形态(独立的节点还是类库)。有一点我们应该时刻提醒自己——不要设法用一种系统结构去解决所有问题,这会让自己陷入无止尽的循环中。那么系统结构到底有哪些呢?我目前接触到的有——C/S结构,心型结构,树状结构,网状结构,用得最多的当属C/S结构。

C/S结构的系统是非常简单直接的,做过网络编程的程序员能够很容易的搭建起来。其特点通俗一点来说就是:客户端所有信息都从服务器拿,所有信息都向服务器上报,另外客户端还会接收服务的通知。举个具体的例子,我想用一个web来管理流媒体服务器,另外还有多个客户端APP可以访问这个流媒体服务器上媒体流。这里使用C/S结构是最好不过的了,web服务作为后台管理,可以对流媒体服务器进行管理和操作,可以为客户端提供登录,媒体信息推送,以及客户端之间的消息交互等。客户端则根据web服务提供的信息向流媒体服务器取流。这里我们并没有让客户端直接向流媒体服务器获取流的信息,而是通过web服务下发,好处是第一,让管理配置工作有专门的模块处理,让流媒体服务器做好自己流分发的事情;第二,web服务做后台管理有着天生的优势(数据库访问接口,MVC框架,工程管理……);第三,以后加入其他服务模块可以参考流媒体服务器的做法,接口可以重用。这种结构非常适合中小型系统,作为初期系统原型,而开发和维护只需要JAVA程序员1枚,C/C++程序员1枚,客户端开发另计。

心型结构,是以某一个节点或者一个集群(对外表现为一个节点)为中心,其他节点通过该中心节点与其他节点进行交互,而中心节点仅仅作为一个中转,本身并不保存这些消息。这种结构与C/S结构很像,消息都是通过某一节点,不同在于心型结构是要在自身隐形,就像我们打电话一样,我们并不知道我们的电话线路经过了多个节点,只要知道对方的电话号码就能够与对方通信。使用这种结构的系统,一般都具有多个相同或者不同功能的节点,各个节点之间彼此需要频繁的通讯,所以通过一个中心节点进行路由是一个方便的选择。在我做过的系统中,核心网产品曾经使用过这种结构。核心网的网关使用的是一种ATCA的硬件架构,我们的产品中有主控板和业务板(接口板)组成,这是个非常复杂的产品,心型的消息框架为应用提供了板卡之间通讯的能力。

树状结构,其实是一种跨系统的解决方案,比如:一个用户从一个系统漫游到另一个系统,一种方式就是在这两个系统之上再构建一个节点,用户同步这个用户的数据。

网状结构,我工作这么久没有使用过,见过其他人用过,但个人觉得用的并不好。

后两种系统结构,我还需要时间去多了解一下,现在不能做过多评述。

 

对redis用法的思考

redis是基于key-value的消息框架也可以作为缓存,数据库来使用。在最近的几个项目中,我都想把redis加进去,作为消息框架使用,但是每次都因为种种原因最后放弃了。在这里简单做个备忘吧。

A项目是一个tomcat+C的架构,前端使用了strut2。现有架构中使用了thrift作为消息框架,每个模块自己定义消息来进行交互。如果引入redis的话,除了可以使用现成的消息框架(包括消息订阅与发布功能,这在thrift中得自己定义)以外,更重要的是各个模块的消息交互可以保持一种统一规则,而且还可以可借助redis的tools方便调试。但是在现有框架下引入redis显得有点冗余,因为前端已经使用了strut2这种重量级的WEB框架,不可避免的,我们需要添加一些业务对象来做redis接口的适配,而这个适配层其实自己就可以作为缓存而存在。

B项目中,我想引入redis保存server的client实例,这样UI显示部分可以直接从redis获取实时信息。但最后,我认为还是server自己管理上下文简单些,一是写个list加个lock很省事;二是,把list上报给UI也用不了几行代码。因此没有必要,再多引入一个节点。那么如果要用redis的话,应该怎么用才合适呢?

首先,我认为UI部分应该承担比以前更多的工作,为了避免引入适配层,在web后台应该使用通用的方法来处理redis的请求与返回,比如使用json格式来传递消息,甚至在UI部分可以直接使用redis的语义,这用后台可以直接透穿给redis。这种方法可以极大的减少web后台原来的工作(想想strut2中,写的那些个action)。而C程序中,也应该直接面对redis来编码,虽然自身的context还得不能避免,但是至少统一了与上层的消息接口。

这里只是想把redis作为消息框架使用,其缓存功能,我暂时还用不到。

零配置

关于零配置,最早我是在2010年做WLAN的时候了解到的。当时运营商的规范里面要求瘦AP架构下,AP要能够零配置启动。一个概念我当时第一感觉就是——简单,易维护。后续的VIS 2.0设计里面也沿用了这种集中式配置+客户端零配置的做法。最近在做RS重构,对这种架构有了更深一层的认识。

RS里,配置管理是一个非常重要的部分,另一块,就是media gateway。这里主要考虑media gateway的配置如何实现,由于media gateway很多库都是c/c++实现的,而且对效率比较敏感,所以用c/c++是顺理成章的事情。它的配置,其实非常简单,用1,2个table就可以满足需要,那么到底放在自己这块用c/c++实现呢,还是放到统一的配置管理服务上实现呢?

假如media gateway是一个单独的小产品,我们当然希望越简单越好,让media gateway自己保存配置。但是当它作为整个RS系统的一部分的时候,我们不得不从整体来考虑,这时候将配置管理部分抽离出来让一个平台来解决这些公共的功能才是最合理的做法。另一方面,让平台来做还可以借助第三方工具,一来提高了效率,二来而不用担心media gateway的代码过于臃肿。举个例子,系统平滑升级,我们需要考虑数据结构发生变化的时候,如何将现有数据迁移到新的结构中。这其实在JAVA中,比如hibernate,已经有很多工具/方法可以解决这种问题,我们甚至都不需要自己写SQL语句。但是在C/C++中实现这种功能,就会有点繁琐,甚至会影响性能和稳定性。

最后总结下一下,单独的小产品,自己管理配置最好不过。对于大系统而言,由平台统一管理才是王道。