微服务应该多大

转自:https://zhuanlan.zhihu.com/p/143709876?utm_source=wechat_session

该文章和作者很厉害.

微服务实践最常见的错误之一是把微服务做得过小。本文通过示例,深入讨论了微服务的大小和粒度。

微服务架构终于成为一种架构模式。与任何新技术一样,微服务的发展符合 Gartner 的技术曲线。从推特上获得的信息来看,它处于低谷期或复苏的早期阶段。换句话说,过去6年,我们在构建微服务方面积累了一些重要经验,其一就是确保以恰当的方式考虑每个微服务的范围。

https://www.gartner.com/en/research/methodologies/gartner-hype-cycle

众所周知,微服务容易把人往“沟里带”,并没有解决实际问题。当你想到“微服务”一词时,首先看到的是前缀“微”(Micro)。据 An Introduction to Greek 一书的介绍,在柏拉图和亚里士多德那里,μικρός只表示少或小。在日常英语中,“微”往往表示小得异乎寻常的东西——毕竟,“微米”是一米的百万分之一,而“显微镜”是用来观察那些肉眼看不见的东西,因为它们尺寸太小。

问题就出在这种不同的认知上。与之前的大型单体服务相比,微服务应该是“小”的。然而,它不应该太小——把微服务做得过小是很多团队实现微服务架构时遇到的最常见错误之一。

正是这种“微服务必须非常小”的思想导致这个问题。关于微服务,我们经常听到的另一个抱怨是,在银行等复杂领域使用它们太难了,因为所需的 REST 或消息传递接口没有提供跨多个微服务进行两阶段提交的方法。每当我们听到这种抱怨时,头脑中的警钟就会响起——通常,这种抱怨是一个症状,表明团队把他们的微服务看作是非常微小的东西。

为解决这个问题,让我们从一个简单的示例开始寻找解决方法,然后再回过头来,进一步考虑该解决方案对整个微服务架构的影响。

示例从设计一个简单的 Account 服务开始,从这个没有包含微服务实现的设计开始,以便你能看清它的演进过程。假设团队正在使用领域驱动设计(稍后会详细介绍),在他们的第一次尝试中,发现 Account 实体需要引用两个关联依赖实体——Entry 和 Owner。

 

 

最初的 Account 设计

很快,团队就发现 Account 上有一些定义良好的操作:借、贷、开、关。幸运的是,这些操作可以很好地映射到 REST 接口,因此,采用这种简单的基于实体的设计并将其映射到微服务实现起来比较容易。然而,他们很快就发现问题——他们还没有弄清楚账户之间如何进行转账,如下图所示:

 

 

具有 Transfer 服务的 Account 设计

问题是,在账户之间转账需要一个全新的 REST 接口,这一点显而易见。问题是如何实现,这是否代表一个全新的微服务?

最简单的假设是(也是许多团队都会采用的假设),微服务和 REST 接口之间应该存在 1 对 1 映射。然而,当把这个映射关系应用示例中时,我们很快就遇到一个问题:新的微服务如何实现?最简单的方法似乎是让 Transfer 微服务调用 Account 微服务两次;一次从“from”账户借出,一次贷入“to”账户。所以,我们的实现可能是这样的:

 

 

调用其他服务的服务实现

但这将陷入前面讨论过的两阶段提交问题!如果借出成功,贷入失败,那么这个客户账户里的钱就少了,还没有任何追索权。这种情况显然是不可接受的;因此,许多团队尝试了以下解决方案:

 

 

在数据库引入耦合的 Account 设计

这解决了两阶段提交问题,但是在数据库中引入耦合,违反了微服务设计的原则之一,即服务应该拥有自己的数据,而不是通过共享数据库“隐式”耦合。正确的做法是什么呢?在我看来,许多团队都“走远了”,并开始追求涉及 Saga 模式的解决方案,以便通过补偿事务来处理问题。虽然 Saga 模式可以解决问题,但它不是这种简单情况的最优解决方案。

考虑一下下面的解决方案,它打破了之前的那个假设:

 

 

在服务边界暴露多个服务

在这个解决方案中,我们重新考虑了之前假设的那个约束——一个微服务正好对应于一个 REST 接口。这个假设已经写入网络上的许多微服务教程中。然而,如果你仔细阅读 Fowler 的原始论文,就会发现其中从未指出过这个假设。在微服务边界上可以暴露多个服务。但这并不是这个小练习的真正目的。让我们回到主题,通过这个练习来阐明更常见的问题。

https://martinfowler.com/articles/microservices.html

我们在上文中说过,示例中的团队使用领域驱动设计作为其微服务设计流程的一部分(要了解更多信息,请阅读 Eric Evans 的著作《领域驱动设计:软件核心复杂性应对之道》)。

在这方面,团队是对的。我们看到,在微服务设计领域,其中一个最大的问题是,他们经常不是从领域驱动设计这样的技术开始,而是从其他地方开始,比如从现有系统的设计开始,并试图从那里得出自己的微服务。或者,从一个架构开始(通常以工具和框架的形式指定),然后尝试让微服务“有机地”发展。在这两种情况下,最终得到的都不是我所说的微服务——它们往往非常注重技术,与企业业务完全无关。

而我们所说的微服务是用业务术语描述的“业务微服务”,业务人员可以识别它们,并可以从设计中找到它们。设计不足的症状之一是解决方案中很少或基本没有业务微服务,这是因为没有从业务词汇表开始设计。从业务词汇表开始设计是至关重要的一步,这就是为什么我们建议所有构建微服务的团队将领域驱动设计作为其设计过程的一部分。

如果不首先从业务词汇表入手,那么通常会搞成如下架构:

 

 

你们很多人看到这个可能会说“这到底有什么问题吗?”这看起来就是我们要的微服务架构!要回答这个问题,我们必须回顾下 Fowler 在他最初关于微服务的论文中提出的观点。他和 Lewis 提出的观点是,当你的团队由技术专家组成时,所生产的软件也将按技术领域进行组织——这就是实践中的康威定律。Fowler 的解决方案是,按业务能力组织跨职能团队。

当你开发一个与上文类似的微服务架构时,就已经回到了微服务本来要解决的问题!你不仅重新创建了一个单体,而且还是一个分布式单体,情况变得更糟糕了。这违反了可能是 Martin 写过的最重要的一句话:

Fowler 的分布式对象第一定律:不要使用分布式对象。

那么,更好的架构应该是什么样的呢?首先在最上层,考虑下垂直画线,而不是水平画线。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值