Gavin on Backend Technology

backend and more

五种常见的架构模式

引言

最近难得有点空闲时间, 花了点精力了解了下架构的相关知识. Java程序员大多听说过GOF的设计模式, 而软件架构领域也不例外, O'reilly的开源电子书《Software architecture patterns》介绍了常用的五种架构模式. 其中有我本人有实际开发经验的就有四种,另外一个模式也是目前云计算领域比较流行的模式. 这些模式着眼于不同的角度,我根据我认为从小到大的顺序分别介绍一下.

分层架构

分层架构应该是最常见的架构模式,SSH(Structs, Spring, Hibernate)简直就是事实标准. 分层架构通常有如下几个层次:

  • 展现层
  • 业务逻辑层
  • 持久层
  • 数据库层

有时也将业务逻辑层和持久层合二为一.

优势

分层架构最大的优势是每层可以只关注一种需求,更严谨的叫法应该叫"separation of concern". 相对早期的架构,这样的模式更清晰可维护.

劣势

举个例子: 在Palm的云服务时期, 云端服务也是一个分层架构,但是同时也是一个单一应用(monolithic application),这样导致的结果就是虽然我们都有不同的层次, 但各个小组都在同一个应用项目上开发, 代码膨胀并且相互影响, 部署起来也比较麻烦. 比如我的小组主要负责应用商店的搜索功能, 而另外一个小组负责帐号管理功能, 我们之间的关联其实比较低, 但却要在同一个非常庞大的(还有如备份服务,消息服务等多个服务)代码项目上做开发, 经常出现代码冲突, 部署计划也经常不协调, 结果是开发和运维同事都苦不堪言. 于是后来重构,引入了下面要讲的微服务架构

微服务架构

微服务的基本理念是,一个服务只负责一个功能.

一个普通的WEB应用,通常都要处理从帐号注册, 管理, 安全,到具体的业务功能. 而这些功能都集中在一个应用里. 微服务的理念就是在所有的功能里, 将相似的一组功能单独成为一个独立的应用. 比如我们的组织里将Palm的云服务分为账户管理, 登录管理(oauth等), 搜索功能, 存储功能等.

p.s. 这种架构模型正好处在cube scale模型的y-axis模型(其他的两个分别是y-axis和z-axis, 详见:http://akfpartners.com/techblog/2008/05/08/splitting-applications-or-services-for-scale/)

优势

微服务架构简直就是程序员的福音, 运维的噩梦(可能没那么遭 :P). 开发的同事可以根据自己的喜好和业务的实际需要选择开发语言或技术栈, 或采用不同的架构, 而实际部署上也可以根据不同性能需求分配不同的资源(x-axis). 这也为敏捷开发提供了基础.

劣势

开发调试会变得更麻烦. 尤其各个服务相互依赖的时候,一个服务出问题所有的服务都会受牵连. 这个时候一个稳定的, 易部署的开发和集成环境变得非常重要. 关于如何利用目前的虚拟化和云计算技术搭建集成环境也是一个非常吸引人的话题. 有机会可以另开话题讨论.

事件驱动架构

如果业务逻辑较复杂, 或横跨多个应用时, 如何管理这些业务流程成为一个问题.

事件驱动的架构将复杂的业务逻辑划分成一个个独立的时间处理模块,各个模块之间没有紧耦合的关系, 而是通过关注特定的事件输入,经过处理后产生特定的事件输出, 这个输出事件可以成为另外一个事件处理器的输入. 建立事件的输出与输入之间联系的可以是第三方中间件,比如消息队列. 根据事件消息的协调方式, 该模式可以再分为"协调者"的事件驱动模式和"代理人"的事件驱动模式.

基于这样的模式的产品诸如jBPM等.

优势

划分后的事件处理器逻辑简单,扩展和维护都比较简单. 并且这种架构的优势一旦和非阻塞的编程框架结合,可以给性能带来极大的提升.

许多开发语言都采用一个请求对应一个线程(或进程)的模式. 这样的模式的代码通常比较清晰, 也比较容易调试, 因此被广泛采用. 但是随着并发量的上升和微服务架构的引入, 一个问题会比较突出: 流程中任意一个地方出现阻塞请求,则整个线程或进程被挂起.当并发数量逐渐提升后,对CPU和内存压力也逐渐提高,可能CPU花在线程切换的时间比实际处理逻辑的时间还要多, 造成了很大的浪费.

而非阻塞的编程模型则没有这样的问题, 任何一个原先需要阻塞整个线程/进程的操作都不会造成整个线程/进程的阻塞.

劣势

由于各个事件处理器被划分,并且可能部署在分布式的环境下,造成一个事件处理流程不能纳入一个单独的事务管理单元.

微核心架构(插件架构)

微核心顾名思义就是核心处理单元比较轻量, 而将主要的业务逻辑交由插件来处理. 这么说可能你会将插件和上文提到的事件处理单元相互混淆. 我认为他们的主要区别在于从不同的角度观察和分析问题, 插件模型关注插件与核心的关系, 而事件处理其则只能说明, 该单元的输入和输出为事件. 这两个特性并不相互排斥, 事实上我就开发过一个系统可以同时称为事件驱动和微核心架构.

优势

将业务逻辑以插件的模式封装, 并以合适的接口与主系统相连, 是对业务的一个清晰划分.并且也对业务逻辑的扩展提供了非常好的基础.

劣势

调试相对麻烦

基于空间的架构(或者叫云架构更合适)

本人对这个模式的理解相对模糊, 只能尝试阐述下自己的理解. 我认为这个模式有两个关键词: 去中心化(的数据库), 自动扩展.

第一个关键词是修饰数据库的, 也就是说这个模式要求分布式的数据存储, 建议以分布式的内存为宜, 我个人认为并非一定要内存存储, 因为是否用内存存储主要基于读写速度, 目前一些NOSQL数据库即使不采用内存读写也可以提供较快的读写速度, 比如LevelDB. 分布式的数据存储带来的问题是如何实现数据的同步, 为此需要有数据同步引擎来处理同步.

另外一个关键词是自动扩展. 自动扩展包括计算节点(可以理解为应用层)和数据节点.

为什么MVC不在此列

一个非常常见的面试题(尤其是面试面向对象语言的同学)是:你了解哪些设计模式? 不少同学会回答MVC模式. 我个人有点犹豫是不是该MVC模式和其他设计模式并列, 但是我认为MVC模式可以认为是一个设计架构的模式. 尤其是目前MVC模式已经不只是在服务器端了,在javascript的客户端编程中也大量应用了MVC模式(如:angular).

所以MVC模式有没有被认为是一个架构模式并不重要,因为模式本身就是人们对解决问题最佳实践的一个总结, 一个模式的概念也会不停地演进, 我也相信一个架构师在设计架构的时候不仅仅只有本文所列的五中模式可供参考.

Comments