架构思考续
对于架构设计的思考前面已经写过不少文章,特别是在互联网应用出现后在传统业务系统架构的基础上增加了新的一些特性和设计思路,该文重点想说明下架构设计的一些演进方向。
组件化开发思路在很早以前就已经提出,只是当时的组件间交互更多的谈接口而非服务,同时也没太关心单个组件本身的全生命周期管理。谈组件的时候一定不要先谈开发和技术框架,而是真正从业务架构和应用架构出发去考虑整个业务系统的组件划分,其中包括了业务组件和技术组件,各自应该暴露业务和技术服务能力。业务能力组件化和组件能力服务化也是一直强调的SOA核心思想。
在组件划分清楚后,需要优先考虑组件间的交互而需要暴露出来的服务接口,即组件之间只能通过服务进行协同以进一步实现组件间的松耦合。其次才是考虑单个组件在实现的时候,结合分层开发技术框架涉及到分层,在这里可以进一步参考领域模型驱动和设计的思路,否则很容易实现为数据库表驱动功能而不关心领域模型设计和领域逻辑的实现,即虽然技术框架分层了但是职责不清,逻辑混乱并多处实现。
组件内部的实现一个重点就是应用层和领域层之间的关系,即在应用和领域层之间增加了一个服务层,服务层重点是服务接口和服务的组合等工作,而具体业务规则和数据处理的逻辑在仓储类和规则类里面来实现。注意对于组件内部应用层和领域层交互的服务并不一定要做为分布式的Service服务,也可以直接使用内部的API服务接口即可。将服务层服务接口具体的逻辑实现分离的一个重点就是在后期很容易将服务接口发布为一个供其它组件远程调用的服务方法。
对于单一的技术往往很难满足互联网业务场景下不同的功能需求和非功能性需求,对于不同的功能或技术实现往往都需要选择大量的开源组件或技术进行集成。但是这些独立的技术组件如何集成为一个高效的整体就变得相当重要。任何技术的选择都必须为了业务需求服务,模式分析是选择技术的一个重点,即在什么样的业务场景下,面对什么问题我们究竟应该选择什么样的开源技术来实现最合适。
首先是开发技术框架层面的,即常说的基于MVC模式的多层框架,用的最多的估计还是SSH框架,其中在数据库层面又有Hibernate或 iBatis多种实现,在控制层本身又有struts和spring mvc多种实现。在展现层相关的技术点更多,包括了一些前端基于javascript和jquery的框架引入,Ajax实现,包括当前互联网各种前端响应式框架,Html5技术等。技术框架的选择看似和业务无关,但是却需要进行业务场景分析,包括当前开发的应用是否需要同时支撑web端和移动app端,是否存在和外部集成和服务接口暴露,在业务交互和易用性层面有哪些要求,这些都需要考虑进去。
其次是实现核心技术能力的技术组件,其中包括了缓存,消息,流程引擎,搜索,安全,任务,日志等诸多内容,这些当前往往都有现成比较成熟的开源技术来实现。如通过memcached或redis来实现缓存,通过rabbitMQ或zeroMQ来实现消息和事件管理,基于lucence的全文检索引擎,开源的ETL技术实现数据集成,开源的jbpm流程集成等。在选择这些技术的时候要注意和前面整体技术框架的集成,技术组件应该保持其高内聚和独立性,仅仅技术组件的能力通过服务暴露出去实现和上层应用的集成。要做到这一点往往就需要对开源组件进一步进行封装和定制,以和技术框架形成一个完整的整体,同时又不要把底层技术组件的复杂度暴露给业务功能的开发过程中。还有就是互联网应用还涉及到外部技术服务能力的引入,如外部的邮件通知服务能力,地图能力,支付能力,各个外部开放平台开发的各种内容提供服务能力引入等。对于外部服务能力的引入建议是要在技术平台层单独进行管理和封装,即在技术能力层有独立和统一的服务代理。
最后是数据库和持久化层,包括常见的关系数据库,半结构化和基于key-value的redis,mongoDB等数据库,还有就是完全基于 hdfs的非结构化文件存储能力。对于不同的业务场景和业务对象,往往需要底层不同的数据和存储能力进行支撑,如何形成一个完整能力的数据库服务能力层是架构设计时候需要考虑的。
去IOE化
对于去IOE化是这两年互联网架构设计谈得最多的问题,即去掉小型机,集中存储和商用数据库。如果简单来说下去IOE化的核心就是基于开源的类似Mysql数据库和集群技术,通过X86服务器硬件资源来实现和原来使用IOE架构时候同样的性能和高可用性。在之前淘宝有开源的corba基于 mysql数据库来实现分布式数据库和集群,现在有开源的MyCat来实现,核心就是提供一个DaaS服务层和封装,来实现高性能和高可用的数据库中间件产品。
对于去IOE的热度在当前已经有所下降,这里面有两个原因一个是本身技术成熟度和CAP原则约束,一个方面的原因就是在去IOE和引入DaaS 数据库中间件后本身是增加了架构复杂度和应用开发难度。一个方面是由于DaaS层引入导入的分布式事务问题和对于跨库查询和Sql语句本身的约束增加。一个是在架构设计中就需要考虑前端业务如何进行组件化,业务对于的数据存储如何进行分区和分片,究竟如何进行水平拆分和垂直拆分。
可以讲在架构设计中的去IOE设计和前面讲到的组件化和服务化设计思路密不可分,同时在去IOE下的组件化是彻底的组件化,即组件本身对应的数据库也是独立的,组件可以拥有完全独立的硬件资源和全生命周期管理。因此如果组件没有划分,在后期业务功能实现中就可能导致大量的跨库操作和分布式事务问题。这些都应该在架构设计阶段就思考清楚并制定清晰的架构设计约束,任何架构设计都不会有普适性的通用架构存在,架构约束定义是一个架构要发挥其高效能力的关键。
去中心化
首先来看一个最简单的场景,即客户和请求端是A,服务提供端是B,对于服务提供端已经实现为了分布式集群即(B1,B2,B3...Bn),在这种场景下可以看到对于请求会转发不同的集群节点进行处理。但是对于这种分布式架构来看,集群是可以完全平滑弹性扩展的,但是问题关键点在于A的请求究竟应该转发到哪个B节点去处理,这里面就有一个控制层或管理节点,而对于大多数分布式应用来讲管理节点本身是很难集群化扩展的。及时当前很多分布式架构实现过程中已经实现了消息请求和数据传输的分离,但是仍然存在对于管理节点无法水平扩展的问题。
对于水平弹性扩展问题的解决,往往会引入集群技术和硬件负载均衡,但是这不是一个完全意义上的去中心化架构,当前我们说的去中心化架构都是没有统一的管理节点,完全分布式,只有在这种架构下才是完全的去中心化。要做到去中心化就涉及到几个关键点的引入,一个是请求通过sdk包在客户端的植入进行前移,即客户端发起请求的时候就已经判断清楚;其次是对于管理职责后移,即管理端后续重点是从各个集群节点准实时采集数据再进行分析。要实现第二点往往又涉及到高性能的消息中间件的引入。