背景
我们在聊架构风格之前先明确一个问题,什么是架构?我们为什么要选择架构?用来解决哪些问题?
什么是架构
书本定义:“软件的架构是一种抽象的结构,他由软件的各个组成部分和这些部分之间的依赖关系构成”。
我的理解是,架构就是根据业务选择合适的技术、中间件,并且按照合适的设计模式对这些模块,进行组装来满足业务特性的需求。
选择架构风格的目的
我们选择架构风格的初衷在于 “三更原则”(自己的理解) :更好地降本提效、更快地发版上线、更好地维护系统稳定性。
任何一个架构风格,都可以实现功能性需求,但是一个好的架构风格能在功能性需求之上,提升非功能性需求。那么你可能会问,什么是非功能性需求?举例:扩展性、稳定性等等。
这里将会以我认知结合踩过的坑,来给大家详细讲一下,我们是如何从单体架构演进到分布式架构。在向分布式单体架构的演进的道路上,又是如何进行的抉择,以及为什么最后同时选择了 微服务架构+分布式架构 的原因。接下来就结合一个系统来作为案例,贯穿主线讲解。
首先来讲一下,最初的单体架构的经历和转型。
单体架构
我们在系统创建之初,往往都是集中业务、单点部署系统,所有业务打一个包,快速上线。满足了业务初期的快速发版上线,而且适合中小公司没有自己的 PaaS 平台,应对初期快速迭代的业务,开发、迭代、测试、发布都是非常的便捷。那么单体架构都有什么类型呢?
单体架构类型
单体架构也分为大泥团架构、分层单体架构、模块化单体架构,他们的区别是什么呢?
-
大泥团单体架构:毫无分层、所有模块聚焦在一起,相互穿插(除非是你接手需要改造,否则不要创建这样的架构风格。这种大泥团架构很难拆分,到最后的下场往往都是重新搭建);
-
分层单体架构:普遍的选择。架构进行了简单的分层,比如传统的 MVC 三层架构;
-
模块化单体架构:一般是随着业务的发展,由分层单体架构演变而来,特点就是引入了多个业务模块并且提供相应的服务能力。
单体架构的优缺点
优点
-
应用的开发很简单
-
易于对应用程序大规模的更改
-
测试相对简单、直观
-
部署简单明了
-
横向扩展不费吹灰之力
在业务的初期,单体架构的优点,无论从哪个方面来说,都优于其他架构风格,但是随着业务的增加、耦合,单体架构的缺点也逐渐暴露出来,这个也符合“康威定律”。那么单体架构的“后期”会暴露出哪些问题呢?
缺点
-
代码库膨胀
-
过度的复杂性会吓退开发者
-
开发速度慢
-
从代码提交到实际部署的周期很长,而且容易出问题
-
难以扩展
-
系统的稳定性得不到保障
-
需要长期依赖某个可能过时的技术栈
单体架构的这些缺点,其实影响的还是我上面提到的“三更原则”。经过上面的铺垫,相信大家已经对单体架构风格已经有了简单的理解。
光有方法论是不行的,我们得结合项目以及代码片段来加深理解,做到真正的应用。接下来我就用一个库存系统来进行串联进行讲解。先通过这张图来了解下库存系统是用来做什么的?
-
创建之初,1 个服务提供商品库存维护、库存查询、库存扣减能力。
-
随着业务的发展,库存面向多个服务:B 端业务,平台内部业务系统、平台外部中台。C 端业务,订单商品扣减库存、网关查询库存数量。
单体架构的案例——库存系统
最初的库存代码分层如下:
-
api:对外提供的 Dubbo 服务
-
common:封装了公共方法
-
dao:封装了数据库 DHCP 交互
-
domain:实体类
-
inner-api:系统内部 API 交互
-
router:废弃
-
rpc:上下游 RCP 交互
-
service:业务逻辑层
-
web:Web 服务层
-
worker:任务调度层
在最初很长的一段时间里,我们部署了两个单体服务。一个是 API 接口来保障上游的库存查询以及调用,另一个是 Web 服务的后台管理平台。这两个单体服务很好的贴合了最初的业务迭代和发版速度,但是后来随着业务的增加附加调用量的增加,单体服务的无论是从性能和稳定性都出现了较大的波动。
意料之外,情理之中的事故惨案
2015 年 6 月 26 日晚,也是一个促销活动的前夕,库存的 Web 管理平台挂了,原因就是大量库存导入,服务器的内存不足导致机器宕机。商家、运营无法通过导表的方式去维护库存数量,在这之前已经经历过了多次横向扩容。还是出现了预料之外的流量和稳定性的问题。