大多数开发人员都在规模较小的公司工作,可能最多 50-80 名开发人员,不需要进行大规模扩张。在这种情况下,正确构建的单体(Monolith)系统要优于构建基于微服务的系统。有了一个结构良好的单体系统之后,必要的时候也可以很容易地把服务迁移出来。
大多数开发人员并不在 Netflix 或 Spotify 这样的全球大型公司工作,Jan de Vries在柏林MicroXchg的演讲中指出,大多数开发人员都在规模小得多的公司工作,可能最多 50-80 名开发人员,不需要进行大规模扩张。他认为,在这种情况下,正确构建的单体(Monolith)系统要优于构建基于微服务的系统。有了一个结构良好的单体系统之后,必要的时候也可以很容易地把服务迁移出来。
De Vries 在4DotNet担任顾问,同时还是 Azure 的Microsoft MVP。根据他的经验,向微服务转移的常见原因是需要扩展,对他来说这是一个合理的理由。另一个原因是团队可以自由选择喜欢的开发环境和技术堆栈,有时因为现有的需求,这样做这是合理的。但他指出,这种自由可能意味着一家公司必须维护几个非常不同的环境,代价可能非常昂贵。
De Vries 认为,单体通常易于部署和运行,它的体系结构适合许多应用程序。假如某个地方出现故障,则整个应用程序都会出现故障,这样我们就知道出问题了。大多数时候,我们知道如何修复它,并可以快速地重新部署。它很健壮,通常经得起时间的考验,我们中许多人应该都在维护一个 10 年前构建并仍在运行的单体解决方案。而他遇到的几个微服务解决方案在构建后的三年内相当脆弱,不得不进行重构。
大多数的单体设计得并不是很好,也很难维护,De Vries 认为这是很多开发人员不喜欢单体的原因之一。但是,设计和构造一个得当的单体会带来工作上的乐趣。他认为它的设计应该像筒仓(Silo)一样,每个逻辑的功能部分都包含一个入口点和输出,不与其他筒仓共享任何逻辑或数据。这样设计,当有不同的扩展需求的时候,很容易将筒仓迁移到单独的服务中。
De Vries 最早接触的一个微服务设计是由几个小的实体服务构建的,每个实体服务对应一个公共数据库中的数据库表,工作时彼此依赖形成一个分布式单体。讽刺的是,它所存在的业务故障,反而可以作为性能特性来宣传。当业务部门抱怨性能缓慢时,可以直接执行 SQL 查询,而不是对另一个服务进行 REST 调用,这样性能可能会提高 10 倍。
另一个项目中,De Vries 承担部分工作,从一些具有单独任务的小型服务开始,但它们都共享同一个数据库。这是反模式的,因为如果数据库中的某些内容发生了更改,所有服务都会受到影响。另一个问题是,由于在服务之间使用同步调用,如果一个服务失败,与失败服务通信的所有服务也将失败。在这些年中,服务的数量增加到了近 50 个,所有的服务都在不同的层次上进行交互。因此,他称这是一个巨大的分布式单体,有一个官方名称: 大泥球。由于存在所有的痛点,系统目前正迁移到具有更独立的服务的设计中。
De Vries 倾向于系统为每个业务功能设计一个 Silo 或服务,这意味着每个功能都成为一个命令式或请求式处理程序,处理业务功能所需的一切。通常,服务需要共享一些数据,但他建议使用某种消息总线发送消息,而不是在服务之间使用同步调用。然后,不管哪个服务发送消息,每个服务都可以读取它所需要的消息。这样隔离不同部分的好处是,它们可以根据需要使用不同类型的技术堆栈和数据存储。De Vries 指出,虽然你可以这样做,但并不意味着必须这样。他是保持简洁的支持者,更喜欢使用单一的技术堆栈,除非有充分的理由换成其它方案。
如果不共享任何业务逻辑,最终可能会产生大量的重复代码。重复的代码是糟糕的(DRY),换言之,我们应该以某种方式抽象出重复的代码。De Vries 之前遵循了这条规则,这导致现在的解决方案包含数千个接口,并且类中存在许多组合,这使得代码库非常复杂并难以理解。对于新的团队成员来说,理解代码并做一些有用的事情可能需要几个月的时间。这对 De Vries 来说是大量时间的浪费,而随着抽象的减少和代码复制,他相信时间可以缩短到一至两周。决定是否复制要考虑的一个重要规则:两段代码是否要一起更改。如果更改的原因不同,就不是复制,而是替代,虽然看起来像复制。
通过消息进行服务通信的另一个优点是,如果业务部门所要求的新功能需要来自多个服务的信息,那么这个服务可以使用自己的存储进行创建。然后,这个新服务可以从消息总线读取它需要的消息,并构建业务所请求的信息。De Vries 强调,服务设计的一个挑战是从业务的角度找到系统正确的边界,这样来设计是很难的。相比之下,为单个服务编写代码和构建对他来说相对容易些。
关联ID,是一种将请求与一个服务关联起来,并将随后的请求与其他服务关联起来的方法。De Vries 称这是由于糟糕的设计导致的 hack 方案,一个请求应该在一个服务中实现,而不需要调用其他服务。从业务的角度来看,它的价值在于,将用户的所有请求关联起来,以了解他或她是如何使用系统的。他强调,关联 ID 的做法应该用于增加业务价值,而不是挽救错误的设计。
在同一次会议上的演讲中,Sebastian Gauder 也谈到了如何将一个单体迁移到微服务。
Randy Shoup 在 2018 年 Reactive 峰会上的演讲中描述了一种使用增量式架构构建系统的方式,声称我们应该从一个简单的体系结构开始,在需要时对其进行改进。在 2017 年 QCon 纽约的一次演讲中,他描述了如何将单体应用增量迁移到微服务中。
Greg Young 在伦敦举行的 Skills Matter 2016 年微服务大会上的演讲中谈到了微服务的悠久历史,我们不应该构建分布式系统,除非确实需要,重要的是服务之间的隔离。
在2015年的博客文章中,Stefan Tilkov 认为微服务的主要好处是在系统的不同部分之间建立清晰和严格的边界。他反对微服务架构应该从单体开始的观点,声称,“构建一个结构良好的单体,具有清晰的、分离的模块,以后可以像微服务一样迁移出来”,在大多数情况下,这样做即使有可能,也是极其困难的。
会议的大多数演讲都已录制,将在未来几个月内公布。
原文链接:Build a Monolith before Going for Microservices: Jan de Vries at MicroXchg Berlin
评论 2 条评论