在设计的前夕,设计人员喜欢把领导对将来业务的指望带入到设计目标当中,好比当前业务也不过是接入几千辆车,将来业务增加也不过几万台,但领导不少激情,强势要求二期平台的接入能力要达到20万台,这个要求带入到架构设计当中,不少人当即崩溃了,在设计的时候,意淫出不少奇妙的东西,很复杂的数据库结构或者库表,在设计的初期就早早的确立一些框架如MQ,Memcached,Ehcache等等,在后来的实际运行过程当中,因为不熟悉,起到反面的做用,性能差,bug多。web
要知道设计和实现,是不一样的人或团队在作,若是设计的思路不能贯彻下去,走样是必然的。sql
这在设计界有个定律,就是设计的越复杂,实现的时候,越难实现,开发周期越长,代码越复杂,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代码剥离出来。大大提升了代码的可读性和可扩展性。