先从单体架构开始
2015 年 6 月 3 日
当我听到关于团队使用微服务架构的故事时,我注意到一个常见的模式。
- 几乎所有成功的微服务案例都始于一个变得太大而被拆分的单体架构。
- 几乎所有我听说过的从头开始构建为微服务系统的案例,最终都遇到了严重的问题。
这种模式导致我的许多同事争论说,即使你确定你的应用程序会足够大,以至于值得使用微服务,也不应该从微服务开始一个新项目。
微服务是一种有用的架构,但即使是它们的倡导者也说,使用它们会产生显著的微服务溢价,这意味着它们只对更复杂的系统有用。这种溢价,本质上是管理一套服务的成本,会减缓团队的速度,有利于对更简单的应用程序使用单体架构。这有力地证明了先单体架构的策略,即你应该最初将一个新应用程序构建为单体架构,即使你认为它以后可能从微服务架构中受益。
第一个原因是经典的Yagni。当你开始一个新的应用程序时,你对它是否对你的用户有用有多大的把握?一个设计糟糕但成功的软件系统可能难以扩展,但这仍然比反过来好。正如我们现在认识到的,找到一个软件想法是否有用的最佳方法通常是构建一个简化的版本,看看它运行得如何。在这个第一阶段,你需要优先考虑速度(以及由此带来的反馈周期时间),因此微服务的溢价是你应该避免的拖累。
使用微服务开始的第二个问题是,它们只有在你找到服务之间良好、稳定的边界时才能很好地工作——这本质上是制定一组正确的限界上下文的任务。任何在服务之间重构功能的操作都比在单体架构中要困难得多。但即使是在熟悉领域工作的经验丰富的架构师,也很难在一开始就确定正确的边界。通过先构建一个单体架构,你可以在微服务设计在它们上面涂上一层糖浆之前,弄清楚什么是正确的边界。它还让你有时间开发微服务先决条件,这些先决条件是更细粒度服务所需要的。
我听说过不同的执行先单体架构策略的方法。逻辑方法是仔细设计一个单体架构,注意软件内部的模块化,包括 API 边界和数据存储方式。如果做得很好,从单体架构迁移到微服务就相对简单。但是,如果我听到过一些成功案例,我会对这种方法感到更加舒服。 [1]
一种更常见的方法是从一个单体架构开始,然后逐渐剥离边缘的微服务。这种方法可能会在微服务架构的核心留下一个相当大的单体架构,但大多数新开发都发生在微服务中,而单体架构则相对静止。
另一种常见的方法是完全替换单体架构。很少有人将此视为值得骄傲的方法,但将单体架构构建为牺牲架构有一些优势。不要害怕构建一个你将要丢弃的单体架构,特别是如果一个单体架构可以让你快速进入市场。
我遇到的另一种方法是从几个粗粒度的服务开始,这些服务比你最终期望的服务更大。使用这些粗粒度的服务来习惯于使用多个服务,同时享受这种粗粒度减少了你需要进行的跨服务重构的数量。然后,随着边界的稳定,分解成更细粒度的服务。 [2]
虽然我的大部分联系人都倾向于先单体架构的方法,但它绝非一致。反驳意见认为,从微服务开始可以让你习惯于在微服务环境中开发的节奏。以一种足够模块化的方式构建一个单体架构,以便它可以轻松地分解成微服务,这需要很多,也许是太多,纪律。通过从微服务开始,你可以让每个人从一开始就习惯于在独立的小团队中开发,并且让团队以服务边界为界限,这使得在需要时扩展开发工作变得更加容易。这对于系统替换尤其可行,因为你更有可能在早期找到足够稳定的边界。虽然证据很少,但我认为,除非团队有构建微服务系统的合理经验,否则你不应该从微服务开始。
我还没有足够的轶事来确定如何决定是否使用先单体架构策略。微服务还处于早期阶段,可供学习的轶事相对较少。因此,任何人在这些主题上的建议都必须被视为暂时的,无论他们多么自信地争论。
进一步阅读
Sam Newman描述了一个案例研究,一个团队正在考虑在一个全新的项目中使用微服务。
笔记
1: 你不能假设你可以将任意系统分解成微服务。大多数系统在其模块之间积累了太多的依赖关系,因此无法合理地拆分。我听说过很多案例,试图分解一个单体架构很快就会陷入混乱。我也听说过一些案例,逐步迁移到微服务取得了成功——但这些案例需要一个相对良好的模块化设计才能开始。
2: 我想严格地说,你应该称之为“双体架构”,但我认为这种方法遵循了先单体架构策略的本质:从粗粒度开始,获得知识,然后进行拆分。