如何实现单体架构到微服务架构的蜕变?

你好,我是看山。

前文我们聊了介绍了单体架构、SOA 架构、微服务架构、无服务架构。如果原来是单体架构,想要切换到微服务架构,该怎么解决呢?本文来聊聊这个话题,解决“什么时候(WHEN)、怎样做(HOW)”。

什么时候

微服务架构是一种架构风格,专注于软件研发效能,主要包括单位时间内实现更多功能,或者软件从想法到上线的整个持续交付的过程。在当前的互联网环境中,业务变化迅速,使用微服务架构,可以让团队迅速反应,快速实施,在方案没有过期之前已经上线运行,经受市场考察和考验。

目前国内大多数公司正在运行的系统都是单体架构系统,不可否认,这些系统在公司发展过程中,发挥了不可替代的作用,保障了公司正常运行,创造了很多价值。但是,随着系统的日渐膨胀,集成的功能越来越多,开发效率变得越来越低,一个功能从想法到实现,需要花费越来越长的时间。更严重的是,由于代码模块纠结在一起,很多已经老化的架构或者废弃的功能,已经成为新功能的阻碍。

单体架构与微服务架构的成本

上图中,X 轴是业务复杂度,Y 轴是单位效益。绿色线条代表单体架构,蓝色线条代表微服务架构。

可以看到,在业务发展初期,系统复杂度不高,业务不够成熟,我们主要经历在于业务试错。如果采用单体架构,可以将所有的功能、模块放在一个进程;如果此时采用微服务架构,我们就需要考虑进程间通信、不可靠网络故障等,还需要实现微服务的基础组件。这个时候,单体架构的单位效益是高于微服务架构的。

随着业务发展,系统承载的功能越来越多,单体架构的劣势凸显,比如:

  1. 硬件能力难以跟上急速发展的业务;
  2. 系统隔离性差,所有功能都在一个进程中,一个功能的异常可能影响其他功能;
  3. 代码复杂度提升,团队合作越来越难,代码冲突的可能性越来越高;
  4. 庞大的代码量,在日常开发、测试时,IDE 难以支持;
  5. 系统构建、部署时间延长;
  6. 技术绑定,没有办法根据系统功能需要灵活使用不同技术;
  7. ……

总而言之,单体架构随着功能增多,不可避免的是研发效能的降低:研发周期变长、研发资源占用增多。从而引发的情况是:新员工培训时间增多、员工加班时间变长、员工要求涨薪或者跳槽。

当达到图中的交叉点时,说明单体架构已经不能够满足企业发展需要,这个时候,需要升级架构来提升研发效能,比如微服务架构。

有人会问,这个时间点不太好把握。我们只需要考虑三个问题即可:

  1. 产品是否已经经过市场考验?
  2. 是否需要超过一个团队来保证产品发布?
  3. 系统是否对可靠性、可伸缩性有较高要求?

如果都是肯定回答,那就该着手准备将单体架构切换为微服务架构了。

怎样做

从单体架构到微服务架构,从一个大一统的系统,拆分成一个一个单独的小服务,我们需要投入精力,做基础的准备:

  1. 先要了解什么是服务、该怎么拆分;
  2. 然后需要搭建基础设施,为拆分出来的服务做好后勤保障;
  3. 最后才是一步一步完成架构切换。

认识服务

首先,什么是微服务架构呢?通俗的定义是:“一组围绕业务领域建模的、小而自治的、彼此协同工作的服务。”

微服务架构中的服务,是根据业务能力抽取的业务模块,独立开发和部署,但是需要彼此配合完成整个业务功能。服务不是单纯的数据存储组件,也不是单纯的逻辑函单元。只有同时包括数据+逻辑,才是真正意义上的服务。

服务拆解过程中,DDD(领域驱动设计)可以作为微服务架构的指导方针。因为微服务是围绕业务功能定义服务,根据服务定义团队,这与 DDD 将业务域拆解为业务子域、定义限定上下文的方法论如出一辙,于是 DDD 作为微服务的指导方针,快速定义各个服务组件,完成从单体架构到微服务架构的迁移。

领域驱动设计

Alberto Brandolini 提出识别服务上下文的方式叫做“Event Storming”。第一步是识别业务域中发生的事件,也就是说,我们的关注点是行为,不是数据结构。这样做的好处是,系统中不同服务之间是松散耦合关系,而且单个服务能够自治。

定义好了服务边界,还需要定义事务边界。过去,我们的服务在一个进程中,后面挂着一个数据库,事务可以选择强一致性事务,也就是 ACID。当服务增多,彼此配合,这个时候可以使用最终一致性事务,也就是 BASE。不同于 ACID,BASE 更加灵活,只要数据在最终能够保持一致就可以了。这个最终的时间范围,根据不同的业务场景不同,可能是分钟、小时、天,甚至是周或者月。

准备工作

微服务架构愿景美好,属于重型武器,优点众多,缺点也很明显。服务增多,运维难度增大,错误调试难度增大。所以需要自动化构建、配置、测试和部署,需要日志收集、指标监控、调用链监控等工具,也就是需要 DevOps 实践。实现 DevOps 的三步工作法 中说明了实现 DevOps 文化的三个步骤。

除了上面提到的基础,还需要在早期确定服务之间如何集成和彼此调用方式,还需要确定数据体系,包括事务一致性和数据可靠性方法。随着服务增多,还需要配置管理、服务发现等众多组件。具体需要的基础组件可以参考 微服务的基建工作

微服务架构中的基础组件

这些基础的服务和设计,最好在早期定义,否则,后期需要花费更多的资源才能够完善架构。如果前期缺失,后期也没有补足,造成的后果就是微服务架构迁移失败,最后的系统也只是披着微服务外衣的单体架构。

开始动手

当我们确定开始使用微服务架构时,接下来的问题就是应该怎么做?是逐步进化更新系统、还是破釜沉舟重构整个系统。

第二种方式很诱人,比较符合大多数技术人的思维,系统不行,推倒重来,名为重构。但是在大多数情况下,这种方式不能被允许,因为市场变化迅速、竞争激烈,大多数公司不会停止业务,去等待重构一个能够运行、只是有些缺点的系统。所以,逐步替换更新系统才是王道,大多数公司也能接受。这种方式又被称为绞杀模式。

该如何逐步过渡到微服务架构?下面一步步进行展示:

实现单体架构到微服务架构:单体架构

第一步,将视图层与服务层部分逻辑进行分离。业务逻辑委托给服务层,支持页面展示的查询定向到数据库。这个阶段,我们不修改数据库本身。

实现单体架构到微服务架构:部分拆分视图和业务逻辑

第二步,用户视图层与数据库完全分离,依赖于服务层操作数据库。

实现单体架构到微服务架构:完全拆分视图和业务逻辑

第三步,将用户视图层与服务层拆分为不同服务,并在服务层创建一个 API 层,用于视图层与服务层之间通信。

实现单体架构到微服务架构:物理拆分视图和业务逻辑

第四步,拆分数据库,将不同业务数据拆分到不同的数据库中,同时对应业务服务层拆分到不同的服务。用户视图层通过 API 网关与不同业务服务层的 API 组件通信。这个时候需要注意,如果团队没有微服务开发经验,可以在这一步基础使用绞杀方式,先抽取简单业务域服务,因为业务简单,实现简单,可以练手,积累经验。

实现单体架构到微服务架构:业务服务层拆分、垂直拆分数据库

最后一步,拆分用户视图层。

实现单体架构到微服务架构:拆分用户视图层

绞杀模式的优势就在于,我们可以随着业务变化随时调整方案,不会造成整个业务进化过程的停摆。

成功标准

If you cannot measure it, you cannot manage it!

If you cannot measure it, you cannot manage it!

引入微服务的目的首先是改善开发流程,我们可以通过简单的指标来衡量:

  • 开发周期:从概念到上线持续的时间
  • 开发效能:单位时间内团队或个人完成的功能或用户故事
  • 系统可伸缩性:系统的水平、垂直扩展能力
  • 平均维修时间:查找和排除故障所需时间

通过对比老架构和新架构的这些特性值,可以评估升级过程取得的效果。我们要时刻关注这些指标,只有一个个小阶段的胜利,才能组成最终完整的胜利。如果再某个阶段失败了,可能达不到我们最终的目的,或者埋下技术债务,后期不得不花更大的代价补偿。

文末总结

想要说明微服务架构的好处,可以来一个比喻。我们建了一个空间站,为此,我们需要将人、货物和设备运输到空间站中,这个时候,运载火箭是比较好的选择,尽管运载火箭造价也比较高,但是几个月发射一次,也能够满足需求。随着空间站的扩大,火箭发射的间隔变短,运输成本高的离谱,而且越来越没法满足空间站运转需求。这个时候,可以尝试另外一种方式,比如,太空电梯。当然太空电梯的造价成本高于一次飞行的费用,但是只要建成,以后的成本就降低了很多。

这个比喻也是说明了微服务带来的美好期望,同时也说明一个问题,实施微服务架构会带来巨大的投资。所以,我们在建造太空电梯之前需要想好,我们真的需要这种投入,否则只能是一种浪费。

作为攻城狮,我们为能够解决或改善周围世界而自豪,着迷于提供解决方案。同时,我们也要意识到,我们付出的每一份努力,都要有回报。如果不能带来任何回报的重构升级,都是浪费时间。

推荐阅读


你好,我是看山。游于码界,戏享人生。如果文章对您有帮助,请点赞、收藏、关注。我还整理了一些精品学习资料,关注公众号「看山的小屋」,回复“资料”即可获得。

个人主页:https://www.howardliu.cn
个人博文:如何实现单体架构到微服务架构的蜕变?
CSDN 主页:https://kanshan.blog.csdn.net/
CSDN 博文:如何实现单体架构到微服务架构的蜕变?

👇🏻欢迎关注我的公众号「看山的小屋」,领取精选资料👇🏻

公众号:看山的小屋