2

如何区分微服务还是分布式单体?

 1 year ago
source link: https://www.jdon.com/66876.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何区分微服务还是分布式单体?

在没有意识到的情况下,基于微服务的应用可以轻而易举地转变为一个分布式单体。

当你意识到这一点时,可能已经太晚了,而且纠正它可能非常昂贵。

所以,就像你勤奋地审查代码和架构以确保它们遵守最好的实践、模式和原则一样,保持警惕并确保你的项目没有潜入这些陷阱也同样重要。在你的项目开发过程中,让这成为一个常规的习惯。

首先,什么是 "分布式单体"?
用非常简单的话来说,它是具有紧密耦合的微服务!!!

在更详细的解释中,一个系统在架构上像微服务一样分布在多个机器或容器中,但仍然表现出类似于单体系统的紧密耦合和相互依赖。

为什么它是坏的

  • 高耦合度:这些服务被紧密地联系在一起,一个服务的改变往往需要其他服务的改变。这大大降低了微服务的关键优势之一:独立改变单个服务的能力,阻碍了敏捷性。
  • 降低了自主性:微服务架构旨在促进服务的自主性,每个服务可以独立开发、部署和扩展。在分布式单体中,服务是紧密耦合的,限制了它们的自主性,使快速创新和迭代成为挑战。
  • 复杂性:分布式单体在管理和理解上可能比传统单体更复杂。你不仅有单体的所有相互依赖关系,而且还有分布式的挑战,如网络延迟和容错。
  • 减少可扩展性:微服务应该是独立可扩展的,允许将更多的资源分配给最需要的服务。但在分布式单体中,服务之间的紧密耦合会使独立扩展变得困难。
  • 缓慢的部署:微服务的目标之一是实现服务的快速和独立部署。然而,在分布式单体中,需要协调多个服务之间的变化,这可能会减慢部署过程。

让我们看看什么会导致分布式单体以及如何克服它。

  • 同步通信:如果你的服务是同步通信的,它们会变得高度耦合。如果一个服务没有另一个服务的响应就不能进行,那么一个服务的问题就会连带导致整个系统的故障。
  • 高度代码级的耦合:使用带有业务逻辑的共享库。共享库的函数签名的变化和其他变化会对多个微服务产生直接影响。
  • 共享数据库:如果多个服务使用同一个数据库,改变一个服务的模式可能需要改变其他服务。这是一种数据耦合的形式,会导致分布式单体。
  • 不适当的服务边界:如果你的微服务不是围绕业务能力设计的,那么你最终的服务可能过于细化或细化程度不够。这可能会导致服务间的高度通信和高度耦合,从而导致分布式单体的出现。
  • 共享部署:如果你的服务总是被部署在一起,那么它们就不是真正独立的。一个服务的改变需要整个系统的部署,这是单体的特点,而不是微服务架构的特点。
  • 缺少模块化:即使服务在物理上是分离的,它们在逻辑上仍可能是单体的。当服务紧密耦合时,就会发生这种情况,它们必须一起被改变和版本化。
  • 集中治理:如果对服务的改变需要由中央团队批准,或者有一个集中的团队来开发共享库或服务,这就会减慢开发速度,减少各个团队的自主性。
  • 事务管理:微服务应该能够处理其数据,以确保松散耦合。然而,在一些业务场景中,你可能会被诱惑去实现跨越多个服务的分布式事务。这种方法会导致紧耦合,因为服务必须协调以确保数据的一致性
  • 服务网的误用:Istio、Linkerd或Consul等服务网格为微服务提供了强大的功能,如弹性通信、服务发现和可观察性。然而,它们不应该被用来实现业务逻辑或导致紧密耦合的复杂通信模式。
  • 避免隐藏的耦合:有时,耦合不是立即可见的。例如,拥有依赖另一个服务的特定行为的服务,如事件的顺序或响应的时间,会导致一种时间耦合,从而使服务难以独立改变。
  • 标准化的误用:虽然拥有标准很重要,但过度的标准化会限制服务团队的灵活性和独立性,可能会减缓开发和创新。确保你的标准提供一个广泛的框架,促进最佳实践,但不限制团队根据他们的具体需求做出决定的能力。
  • 忽视非功能需求:像可扩展性、弹性和容错性这样的方面不应该是事后的考虑。如果在最初的设计中没有考虑这些问题,系统可能会以集中处理这些问题的方式发展,从而导致一种耦合形式,并可能导致分布式单体。
  • 避免过度使用中间件:中间件解决方案(如ESB、BPM)有时可以用来处理服务之间的复杂协调,但这可能导致所有服务都依赖的集中式单体。通常,每个服务处理自己的业务流程会更好。
  • 谨防微服务版本化:在改变服务时保持向后的兼容性是很重要的。如果所有的服务必须同时升级以适应一个服务的新版本,你就进入了分布式单体领域。

让我们来探讨解决这些问题的潜在方案

  • 同步通信:利用异步通信模式,如事件驱动架构或消息队列,以避免时间上的耦合。
  • 高代码级别的耦合:当必须使用共享库时,确保它是向后兼容的,并且是有版本的。
  • 共享数据库:每个服务应该拥有自己的数据库,以确保信息隐藏和解耦。如果数据共享是必要的,就实施数据复制或同步机制。
  • 不适当的服务边界:使用领域驱动设计(DDD),使你的服务与业务领域保持一致,确保每个微服务与业务子领域相对应。
  • 共享部署:确保服务可以独立部署。实施自动化和容器化技术以简化部署过程。一个好的CI/CD管道在这里是至关重要的。
  • 缺少模块化:确保每个服务都是模块化的,可以独立发展。服务应该有一个单一的责任和一个有边界的环境。
  • 集中式治理:采用分散的治理模式,允许各个团队对其服务进行决策,促进自主性和交付速度。
  • 交易管理:避免分布式交易。拥抱像Saga或基于Choreography的工作流的模式来管理跨越多个服务的交易。这些模式确保最终的一致性,同时最大限度地减少紧密耦合。
  • 服务网格的滥用:利用Istio或Linkerd等服务网格,主要是为了运维操作上的考虑,如流量管理、可观察性和安全性。避免依赖服务网格来处理业务逻辑或复杂的通信模式。
  • 避免隐藏的耦合:谨慎对待隐藏的时间耦合,即一个服务的行为取决于另一个服务操作的时间或顺序。分析通信模式、依赖关系和潜在的故障点,以减少无意的紧耦合的风险。异步通信和适当的文档可以提供帮助。
  • 标准化的误用:设定标准,促进最佳实践,确保系统的凝聚力,但允许各个团队灵活地根据他们的具体需求做出决定。
  • 忽视非功能需求:从一开始就考虑到可扩展性、容错性和复原力。让它们成为你的系统架构的一个组成部分。集成诸如负载平衡、断路器和重试等机制,以确保系统的稳定性和响应性。
  • 避免过度使用中间件:每个服务都应该是独立的,并管理自己的业务流程。避免过度使用中间件来处理服务间的协调。
  • 谨防微服务版本化:对你的服务使用版本管理,并确保向后兼容。避免强迫所有服务同时升级新的版本。

构建和维护一个成功的微服务架构需要仔细关注,以避免落入分布式单体的陷阱。保持警惕,审查你的架构,并授权个人团队做出明智的决定,同时牢记服务独立性和灵活性的最终目标。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK