代码改变世界

GPS部标平台的架构设计(二) 可扩展性设计

2014-05-15 17:05  GPS视频平台产品经理  阅读(1946)  评论(0编辑  收藏  举报

在设计的前夕,设计人员喜欢把领导对未来业务的期望带入到设计目标当中,比如当前业务也不过是接入几千辆车,未来业务增长也不过几万台,但领导很多激情,强势要求二期平台的接入能力要达到20万台,这个要求带入到架构设计当中,很多人立即崩溃了,在设计的时候,意淫出很多奇妙的东西,很复杂的数据库结构或者库表,在设计的初期就早早的确立一些框架如MQ,Memcached,Ehcache等等,在后来的实际运行过程中,由于不熟悉,起到反面的作用,性能差,bug多。

要知道设计和实现,是不同的人或团队在做,如果设计的思路不能贯彻下去,走样是必然的。

这在设计界有个定律,就是设计的越复杂,实现的时候,越难实现,开发周期越长,代码越复杂,bug越多,功能越不稳定,性能越差,砸锅的概率越大。

还有一个定律是:大部分设计者只具备了把事情搞复杂的能力,不具备把复杂的事情搞简化的能力,所以领导的期望有多大,设计就有多复杂。

其实架构设计中有两个可扩展性要求:

一个是性能的可扩展,随着接入车辆压力的增大,不需要改动代码,只需要增加硬件配置,如增加服务器,增加软件运行的进程实例来达到要求;

一个是功能上的可扩展,在一个运营平台上,同时为多个不同的物流企业提供运营服务,各个企业必然有自己个性化的需求,想要吸引客户,销售上就得尽量答应客户的各种要求,技术上就要想办法实现客户的要求,但是其他企业客户八竿子用不着。随便一个功能的增加,都要考虑对平台的冲击,多版本的维护,平台稳定性等等。很多运营平台都经历过功能弱智简单、功能丰富最后到臃肿再到最后推倒重来这样的过程,而推倒重来的代价是,罗马不是一夜建成的,架构是美好的,不代表功能的完善和稳定,新版本的不稳定,功能的不完善,给运营又会造成极大的冲击,客户、客服、售后、市场销售等连带着怨声载道,痛不欲生,纷纷追思旧版本如何如何的美好。所以推倒重来的代价是壮士断腕,代价很大,不断也不行,断了就要经历短期的波动。

这两点明确后,我们知道自己的设计目标:

1) 性能可扩展方面

   首先要面向服务进行设计,对子系统当中的调用接口进行定义,在子系统中加以实现,形成服务。这些服务可以本地部署,可以分布式部署,服务的部署对于调用者来说是透明的,不影响的。做到了这一点,我们才可以在压力来临的时候,通过改变和增加服务器的配置,透明灵活的分布式部署方式,来缓解压力的上升。

   面向服务的开发中,对于远程方法调用的协议,Java的有RMI,DotNet的有WCF,都是非常好的可以基于TCP二进制交换数据的协议,远胜于webservice,但在设计的时候,可以完全不用考虑这些,在实现的时候,由于现在的Spring框架很强大,仅仅通过几行XML配置,就可以将一个接口透出变成一个RMI服务或者WCF服务。

  对于压力的处理,愚蠢的设计是在一个功能里反复优化,好的设计往往是分而治之,通过不同的服务,来分担压力,如协议解析、入库、消息通知、应答等分解成不同的服务,解析后调用入库服务,解析程序只是简单调用入库服务的接口然后立即返回,而在入库服务内部,则会通过异步处理保证服务调用后能够立即返回,而不是阻碍整个处理流程。

2)功能可扩展方面

  这个其实是最难的,因为它的要求是比较抽象,就是软件要求能够修改完善添加现有的功能满足软件未来的成长,直白点将就是软件能够改动已满足用户新增的需求。一些人可能会问,只要有代码,可以随便改。如果是这样,为什么我们的客户提出需求后,我们总是拒绝。这是因为随着功能的增多,代码的增多,可维护性变差,修改某个功能的代码,或者添加某项功能,会耗费大量的人力和时间,拔出萝卜带出泥,打扫卫生把瓷器打碎,一句话,很难改。

很多弱智的设计,因为惧怕未来的扩展,所以对实体类和库表都保留了N多的扩展字段,因为不知道未来要做什么用,然后起个无意义的名字,如data1,data2,data3,data4,还有f1,f2,f3这样的字段,应对未来用户扩展要求。这算是扩展设计吗,很难想象,不仅起不到作用,反而制造大量的垃圾,代码的可读性变的非常差。这种设计可以休矣。把可扩展设计理解成冗余设计,预留冗余这种手段称不上设计,未来也肯定用不着。

 什么算是好的可扩展性,只能说,设计好的,代码容易改动,容易添加功能,设计的不好的,一个小小的功能,能改出一头汗,测试的时候,要回归测试一大片。

可扩展性的设计原则只有两个字。

  软件功能可扩展性设计最理想的是基于插件化或者模块化的设计,通过动态加载、事件注册、功能回调等机制,来达到要求,当然插件化的设计的弊端就是复杂,以复杂为代价,甚至要牺牲部分性能,来达到软件的可扩展性。

  插件设计这个在部标GPS服务器的设计中用的比较多,对于不同的终端的协议,可以基于插件化的设计,不同的协议,按照插件标准进行编写,形成一个庞大的协议库,在系统运行的时候,可以静态配置,也可以动态加载,根据不同的车辆,不同的客户,不同的设备,不同的版本,来加载不同的协议插件进行解析。

   善于运用设计模式,也会提高可扩展性,如熟练运用模板模式,善于将数据和表现、格式分离。比如Ibatis框架,通过sql模板,将原有臃肿无聊的sql代码剥离出来。大大提高了代码的可读性和可扩展性。