从单体到微服务:架构入门

2025-06-05

从单体到微服务:架构入门

介绍

https://media4.giphy.com/media/UYgK6kSXD1WDu/giphy.gif?cid=7941fdc6fptefe0fdm2rpfsnozxvox6mvw4065mg2pbhymrp&ep=v1_gifs_search&rid=giphy.gif&ct=g

亲爱的读者,你好!如果你正在读这篇文章,我想你应该已经对网络的运作方式有了基本的了解,并且自己也完成了一些工作,所以恭喜你!

下一个重要步骤是了解一些现有的模式和架构。这不仅能让你构建的软件更加一致,而且从可扩展性到可维护性,也更加稳固。

本文将探讨两种最流行的软件架构:单片架构和微服务架构(以及其中的一些其他重要概念)。

与往常一样,我们就哪一个更好进行了大量讨论,而答案始终是一样的:没有灵丹妙药,您应该了解每种方法的适用情况以及如何在两者之间转换,才能成为一名理性的工程师。

第一个:巨石

https://media4.giphy.com/media/kvT69yjOSlPtGPUexS/giphy.gif?cid=7941fdc6hg2npd5vgfjywwuckuamkd1c4u7j1u1sknwolmrp&ep=v1_gifs_search&rid=giphy.gif&ct=g

如果你不熟悉,单片架构是设计软件应用程序最传统的方法之一。在这种方法中,应用程序被构建为一个单一的单元——我们称之为“单体”,其中软件的各个组件相互连接且相互依赖。

MVC模型

这种架构的特点是单一代码库(通常使用MVC 模式)、共享数据库以及通常单一部署单元。

优势

单片应用程序通常开发起来更简单,尤其是对于较小的项目或团队而言。它们的开发流程非常简单,因为应用程序不同部分之间的交互都集中在同一个地方——这也意味着通常需要更少的 API 调用和数据处理才能正常工作!

部署方面,通常也更容易。由于你只有一个单元,一旦部署完成,所有东西都应该可以正常运行,这意味着你不需要做任何额外的工作。

当我们谈论调试时,它通常更简单,因为整个应用程序在一个单元内运行(这意味着您通常不必在多个应用程序之间跳转来查找问题)。端到端测试也更容易,并且可以在整个过程中顺利进行。

缺点

随着应用程序的增长,一些挑战开始显现。第一个挑战是组织方面的——由于所有内容都集中在一个地方,以保持一个真正大型应用程序的上下文,因此它所经历的所有后果开始变得非常困难(当然,有一些方法可以提前规划,例如模块化单体架构,但当你快速构建时,通常不会考虑这一点)。

第二个挑战是扩展本身。由于整个应用程序位于一个单元内,因此应用程序中特定的使用密集型点将与整个应用程序共享相同的资源。这通常意味着扩展比仅仅“支付更多服务器算力”或“用不同的技术重写该部分”更为复杂。

微服务架构

https://media4.giphy.com/media/3o7TKzhPqGvUDm3pba/giphy.gif?cid=7941fdc6gzzw7dc1eobe4qlg3miho0oxvu4dt4ozve3x0bmc&ep=v1_gifs_search&rid=giphy.gif&ct=g

现在,单体架构的常见替代方案是微服务架构。它是一种将单个应用程序开发为一系列小型服务(这就是“微”的由来)的方法,每个服务都在自己的进程中运行,并通过轻量级机制进行通信以保持所有服务正常运行。这些服务通常可以单独开发、部署和扩展。每个服务通常都有自己的数据库,并通过定义明确的 API 与其他服务通信。

它还有自己的组织模式(有很多著名的书籍介绍这一点),其中最常见的一种是DDD(领域驱动设计)

优势

第一个也是最明显的优势是规模。微服务可以独立扩展,从而提高应用程序各个部分资源的利用效率。由于所有组件都必须以黑盒形式进行通信,这种架构还为不同服务的技术选择提供了灵活性。

第二个原因是,当我们谈论真正大型的应用程序时,微服务代码的复杂性会分散到各个微服务之间。这通常意味着,如果一个微服务出现了 bug,只需派一位团队的新工程师去查看就行了——毕竟,这个 bug 本来就没那么容易存在。

缺点

首先,让所有这些组件正常通信和交互可能是一项真正的挑战。只有上帝知道工程师能花多少时间来查找 Kafka 消息无法到达的原因,或者任何其他可能发生的奇怪问题。管理所有这些组件、它们的基础设施和部署可能非常困难。

第二个是上下文更加细分——从学习代码库的角度来看,这可能是一件好事,但从学习产品的角度来看,这可能是一件痛苦的事——如果你的代码经过 5 个文件而不是 5 个不同的应用程序,那么跟踪起来要容易得多。

最后一点是,微服务有一个需要注意的问题,那就是延迟。如果设计不当,关注点分离和预期的速度提升很可能不会带来回报,因为现在你还增加了一堆不同的调用来让它们进行通信。


有时,当人们创造新的东西时,他们会尝试修复部分问题,这是本文赞助商 Encore 的功能集的一部分:

安可标志

对我来说,一个非常突出的特性是,你无需像平常那样担心不同微服务之间的通信。这真是个好主意——你的开发体验几乎与使用单体应用相同,但同时拥有微服务的全部扩展能力。

建筑流程图

例如,在这种情况下,您可以通过简单地导入一个服务来从另一个服务中调用它

从其他服务内部调用服务

此外,它还提供了大量功能,简化了多服务部署流程。他们正在努力实现两者兼顾,如果您能试用并点个星,那就太好了!

⚡ 明星返场 ⚡


选择正确的架构

https://media3.giphy.com/media/3oKIPqsXYcdjcBcXL2/giphy.gif?cid=7941fdc66769jwvvnan2swwe8q12afmc8k5gdignwevs3s5i&ep=v1_gifs_search&rid=giphy.gif&ct=g

在决定架构时,您需要考虑应用程序的增长潜力、团队规模以及产品的实际复杂程度。

你的应用越简单,你就越能从单体架构中获益。如果你还有疑问,最安全的选择是单体架构——你以后可以随时拆分,但要把它们拼接起来却很难(如果你还有疑问,这里有一个很棒的资料可以阅读:单体架构优先)。

建筑学 主要优势 主要缺点 最适合
单片 简化开发、部署和调试 日益严重的问题 小型到正常大小的应用程序和 MVP(例如DEV.to是一个整体!)
微服务 组件的独立缩放 复杂的管理 拥有多个团队的大型应用程序(例如Netflix使用了大量微服务)

随着复杂性的增加,您可能需要考虑将事物分解开来,因此,让我们来讨论一下如何将整体转换为一系列微服务。

转换:如何从整体迁移到微服务。

https://media2.giphy.com/media/26BGIqWh2R1fi6JDa/giphy.gif?cid=7941fdc6uggvsyc10h6vs8so9wj77mderowc1fc9f8ovssc4&ep=v1_gifs_search&rid=giphy.gif&ct=g

有几种方法可以从单体应用迁移到微服务。让我们快速浏览一下:

  • 全新替代:从零开始创造——不受先前工作的限制,在某些情况下确实很有帮助。但是,当然,我们这里也存在一些潜在的问题(需要多长时间?用户会承受多少时间的痛苦?等等)。
  • 棕地替换:新架构应该与现有软件共存。当我们谈论棕地替换时,与旧/有问题的软件共存可能会带来很多痛苦和头痛。解决此问题的一个有趣方法是“绞杀无花果”模式。我们通常会将旧代码一点一点地包装成绞杀无花果,然后将其重定向到新代码,最终将其淘汰。这使得过渡更加平稳,风险也更低。

一般来说,我们将采取以下步骤:

  1. 在现有应用程序中确定明确的界限。
  2. 从不太重要的组件开始,逐步提取服务。
  3. 将新功能作为单独的服务实现
  4. 重构现有代码库以支持新架构
  5. 确保在整个迁移过程中进行强大的测试和监控→没有什么比盲目地更改应用程序更困难的了

结论

https://media0.giphy.com/media/T9JtEyoJ43gY4wLOqW/giphy.gif?cid=7941fdc6termxktyz4bgwbvc106kw8jauebencv8291a4w6m&ep=v1_gifs_search&rid=giphy.gif&ct=g

嘿!我们经历了一段相当长的旅程。我们讨论了两种主要的架构方法:经典的单体架构(简单直接,但挑战日益严峻)和微服务架构(灵活可扩展,但管理起来复杂得多)。

我希望你现在能够为下一个选择做出选择(或者至少有一个很好的直觉),但是,请记住:没有“一刀切”的做法——如果你要开始一些新的东西,先选择一个整体,如果不是,请仔细考虑!

归根结底,重要的是选择合适的工具。了解这些模式将帮助您根据特定需求做出更明智的决策。请记住:您以后可以随时更改,但务必确保为过渡制定周全的计划!

文章来源:https://dev.to/encore/from-monolithic-to-microservices-architectures-101-3f2e
PREV
如何让你的 Express 应用速度提高 9 倍(并且类型安全)
NEXT
使用 Publish/Sub 在 Go 中构建事件驱动系统