⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 thenewstack.io/microservices-vs-monoliths-an-operational-comparison/ 「thenewstack」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

越来越多的组织开始放弃单体应用,逐步转向微服务的架构模式–将业务流程分为多个独立的服务。

例如,在一个机票预订中,就可能涉及许多个单独的过程:在航空公司预订机票,付款,并在机票成功预订后向客户发送确认信息。

微服务架构,就是将各个流程按照业务拆分为独立的服务。在上面的示例中,机票预订服务可以被拆分为机票预订,付款和确认,拆分后的微服务可以通过接口相互通信。

那么,微服务与单体应用,究竟有什么不同?

对比1:网络延迟

当涉及微服务时,有一个基本的物理定律在起作用,每当微服务通过网络调用另一服务时,字节就通过网络发送,这涉及将字节转换为电信号或脉冲光,然后将这些信号转换回字节。根据模拟结果,微服务调用的等待时间至少为24ms。如果我们假设实际处理大约需要100毫秒,则总处理时间如下所示:

网络延迟-微服务与单体应用

假设在理想情况下,所有调用执行可以同时发生,并且彼此之间不依赖–这称为扇出模式( fan-out pattern)。下图显示了随着越来越多的调用同时执行,总时间如何减少。

同时执行多个调用意味着总执行时间减少

并行执行所有调用,意味着最长的调用执行完,服务将返回给使用者。

从上图可以看出,单体应用没有网络延迟,因为所有调用都是本地调用。即使在完全可并行化的世界中,单体应用仍会更快。而微服务由于需要多个服务间通信,即使并行调用,也是需要一定的网络延迟。

这一次,单体应用胜利了。

对比2:复杂性

考虑复杂性时,有许多因素在起作用:开发的复杂性和运行软件的复杂性。

由于开发的复杂性,在构建基于微服务的软件时,代码库的大小会快速增长。因为微服务涉及多个源代码,使用不同的框架甚至不同的语言。由于微服务需要彼此独立,因此经常会有代码重复。

另外,由于开发和发布时间不一致,因此不同的服务可能会使用不同版本的库。

对于日志和监控方面,在单体应用中,日志记录就像查看单个日志文件一样简单。但是,对于微服务,跟踪问题可能涉及检查多个日志文件。不仅需要查找所有相关的日志输出,而且还需要以正确的顺序将它们放在一起。

在Kubernetes集群中运行微服务时,复杂度进一步增加。虽然Kubernetes启用了诸如弹性伸缩等功能,但它并不是一个易于管理的系统。要部署单体应用,简单的复制操作就足够了。要启动或停止单体应用,通常只需一个简单的命令即可。还有与单体应用相比,事务还增加了运行微服务架构的复杂性。跨服务的调用,很难保证数据是同步的。例如,执行不当的调用,重试可能会执行两次付款。

这一次,单体应用又胜利了。

对比3:可靠性

在微服务中,如果A服务通过网络以99.9%的可靠性调用B服务(这意味着在1000个调用中,有一个将由于网络问题而失败),这时B调用再C服务,我们将获得99.8%的可靠性。

随着调用时间的延长,可靠性下降

因此,在设计微服务架构时,要考虑网络会在某个时刻断开。微服务提供了一些解决此问题的解决方案。Spring Cloud提供了负载均衡和网络故障处理,诸如Istio之类的服务网格还能够处理多种编程语言的服务。当微服务集群中的服务失败时,集群管理器给出替代方案。这就使得微服务架构具有高度的弹性。

Netflix创建了一个名为Chaos Monkey的工具,该工具可以模拟随机终止虚拟机和容器。微服务的开发者,可以使用Chaos Monkey的工具在测试环境模拟网络断连和网络故障等问题,这样,他们就可以确保系统能够处理生产环境中的停机故障。

单体应用中的所有调用都是在本地完成,因此很少发生网络故障,虽然如此,然而单体应用在云环境却无法满足弹性伸缩的需求。

最后,微服务取得了胜利。

对比4:资源使用

一般来说,微服务会比单体应用使用更多的资源。即使在Docker中运行时,基准测试发现,虽然服务连接数量下降了8%,但是容器编排还将消耗资源,日志聚合和监视也将消耗资源。

但是,微服务使我们可以更聪明地使用资源。由于集群管理器可以根据需要分配资源,因此实际的资源使用量可能要低得多。

在软件中,20%的代码一般会完成80%的工作。如果单体应用的一个实例使用8GB,则两个实例使用16GB,依此类推。使用微服务后,我们可以把单体应用中负责主要职能的20%代码提取成一个服务,因此对于两个实例,我们的RAM使用量为降低到了9.6GB左右。

下图显示了资源使用情况的差异。

随着越来越多的实例在运行,单体应用比微服务需要更多的资源

资源使用率方面,微服务胜利了。

对比5:扩展的精确性

单体应用的扩展有多种办法,运行多个实例,或运行多个线程,或者使用非阻塞IO。对于微服务架构,这三个也都是适用的。

但是,面对客户端越来越多的请求,由于微服务架构更精细,因此扩展单个服务也更加精细。所以,对于微服务来说,扩展既简单又精确。而且,由于微服务的资源消耗较少,又可以节省资源。

相比单体应用,微服务精确的扩展和更少的资源使用,是一个明显的胜利。

对比6:吞吐量

让我们再看一个性能指标–吞吐量。在微服务架构体系中,数据需要在不同服务之间发送,从而会产生一定的开销。如果微服务还不是一个分布式架构,那么他的吞吐量还不如一个单体应用高。

对比7:部署时间

人们选择微服务架构的原因之一就是-能够节省部署时间,满足快速迭代。

由于微服务的职责单一原则,因此对其进行的任何更改都有很明确。然而,修改一个单体应用的功能,可能会“牵一发动全身”。

此外,微服务更易于测试。由于微服务仅覆盖有限的一组功能,因此代码依赖性低,便于编写测试并且运行得快。

还有,微服务的资源消耗较少,并且可以按比例扩展。这就使微服务可以无感知部署,例如,可以先在集群一部分节点上启动微服务的新版本,然后迁移一部分用户到新版本,如果有问题,这可以快速回滚到旧版本。

胜利归功于微服务。

对比8:沟通

在微服务诞生之前,弗雷德·布鲁克斯(Fred Brooks)撰写了开创性的著作《人月神话》,本书的其中一项内容是,沟通渠道的数量随着团队成员的数量而增加。由两个人组成的团队,只有一个沟通渠道。如果有四个人,则最多可以访问六个频道。通信通道数的公式为n(n − 1)/2。由20位开发人员组成的团队拥有190个可能的沟通渠道。将这些开发人员分成两个团队,就可以大大减少沟通渠道的数量。

我们以拥有20个开发人员的团队为例,将其分为四个微服务团队(每个团队五个人),则每个团队有10个沟通渠道。四个团队之间的沟通渠道只有六个。沟通渠道的总数为46,大约占20个人团队的四分之一。

下图显示了,一个大团队的通信渠道数量,和单个微服务团队的通信渠道数量的对比。

因此,将10个以上的开发人员分成几个较小的团队,可以为任何开发项目提供更高的沟通效率。

这是微服务的另一个明显胜利。

谁是赢家?

单体应用获得了3场胜利,微服务获得了5场胜利。

但是,在查看此图表时,请记住它是相对的。微服务并不是解决所有开发问题的万能药。

例如,一个由5个开发人员组成的小型团队可能会倾向于选择单体应用。因为,单体应用不仅更易于管理,同时如果软件产品每秒仅有几个访问量,那么单体应用可能就足够了。

以下是一些迹象,表明微服务架构可能是一个合适的选择:

  • 需要7*24的可靠性
  • 精确的扩展
  • 峰值和正常负载明显不同
  • 超过10个开发人员的团队
  • 业务领域可以被细分
  • 方法调用链路短
  • 方法调用可以使用REST API或队列事件。
  • 几乎没有跨服务的事务
文章目录
  1. 1. 对比1:网络延迟
  2. 2. 对比2:复杂性
  3. 3. 对比3:可靠性
  4. 4. 对比4:资源使用
  5. 5. 对比5:扩展的精确性
  6. 6. 对比6:吞吐量
  7. 7. 对比7:部署时间
  8. 8. 对比8:沟通
  9. 9. 谁是赢家?