微服务系统架构如何避免网络瓶颈?


72

我已经阅读了很多有关服务器应用程序的微服务架构的信息,并且一直想知道与整体式架构相比,内部网络的使用是不是瓶颈或明显的劣势。

为了精确起见,以下是我对这两个术语的解释:

  1. Monolith体系结构:一个用一种语言处理所有功能,数据等的应用程序。负载平衡器将最终用户的请求分布在多台计算机上,每台计算机都运行我们应用程序的一个实例。

  2. 微服务体系结构:许多应用程序(微服务)处理一小部分功能和数据。每个微服务都公开通过网络访问的公共API(与同一机器上的进程间通信或共享内存相反)。API调用主要在服务器上进行搜索以生成页面,尽管其中一些工作可能是由客户端查询各个微服务来完成的。

用我天真的想象力,似乎微服务体系结构使用的网络通信速度较慢,而不是同一台计算机(内存和磁盘)上的资源更快。如何确保通过内部网络进行API查询不会减慢整体响应时间?


内部网络通常为1 Gbps,有时更快。考虑一下来自API的JSON响应的平均大小。一秒钟内可以通过1 Gbps连接传输多少个此类响应?
Arseni Mourzenko 2015年


@MainMa问题不在于带宽,而在于延迟。而且,如果您需要往返
旅行

Answers:


61

内部网络通常使用1 Gbps或更快速的连接。光纤连接或绑定允许服务器之间更高的带宽。现在,想象一下来自API的JSON响应的平均大小。一秒钟内可以通过1 Gbps连接传输多少此类响应?

让我们实际进行数学计算。1 Gbps是131,072 KB /秒。如果平均JSON响应为5 KB(相当多!),则仅使用一对机器即可通过电线每秒发送26214响应。还算不错,不是吗?

这就是为什么网络连接通常不是瓶颈。

微服务的另一方面是您可以轻松扩展。想象一下,两台服务器,一台托管API,另一台使用API​​。如果连接成为瓶颈,只需添加另外两台服务器,即可使性能提高一倍。

这是我们之前的26 214每秒响应对于应用程序规模而言变得太小的时候。您添加了其他九对,现在可以提供262140个响应。

但是,让我们回到我们的服务器对并进行一些比较。

  • 如果对数据库的平均非缓存查询平均需要10毫秒,则每秒只能查询100个查询。100个查询。26214条回复。达到每秒26 214个响应的速度需要大量的缓存和优化(如果响应实际上需要做一些有用的事情,例如查询数据库;“ Hello World”风格的响应不符合要求)。

  • 现在,在我的计算机上,用于Google主页的DOMContentLoaded发生了394毫秒。发送请求后。每秒少于3个请求。对于Programmers.SE主页,它发生了603毫秒。发送请求后。每秒甚至不到2个请求。顺便说一句,我有一个100 Mbps的互联网连接和一台快速的计算机:许多用户将等待更长的时间。

    如果瓶颈是服务器之间的网络速度,那么这两个站点实际上可以在为页面提供服务时对不同的API进行数千次调用。

这两种情况表明,网络在理论上可能不会成为您的瓶颈(在实践中,您应该进行实际的基准测试和性能分析,以确定在特定硬件上托管特定系统的瓶颈的确切位置)。花在进行实际工作(将是SQL查询,压缩等)并将结果发送给最终用户上的时间更为重要。

考虑数据库

通常,使用数据库将数据库与Web应用程序分开托管。这可能会引起关注:托管应用程序的服务器与托管数据库的服务器之间的连接速度如何?

似乎确实在某些情况下,连接速度会出现问题,即当您存储大量不需要由数据库本身处理并且现在应该可用的数据时(即大的二进制文件)。但是这种情况很少见:在大多数情况下,传输速度与处理查询本身的速度相比并没有那么大。

真正重要的传输速度是公司在NAS上托管大型数据集的时间,并且多个客户端同时访问NAS。SAN就是解决方案。话虽如此,这不是唯一的解决方案。Cat 6电缆可支持最高10 Gbps的速度;绑定也可用于提高速度,而无需更改电缆或网络适配器。存在其他解决方案,涉及跨多个NAS的数据复制。

忘记速度;考虑可扩展性

Web应用程序的重要一点是能够扩展。尽管实际性能很重要(因为没人愿意花钱购买功能更强大的服务器),但可伸缩性却更为重要,因为可伸缩性可让您在需要时投入更多的硬件。

  • 如果您的应用程序不是特别快,那么您将蒙受损失,因为您将需要功能更强大的服务器。

  • 如果您有一个无法扩展的快速应用程序,那么您将失去客户,因为您将无法应对不断增长的需求。

同样,虚拟机在十年前被视为巨大的性能问题。实际上,将应用程序托管在服务器上与将其托管在虚拟机上对性能产生重要影响。尽管今天的差距要小得多,但仍然存在。

尽管性能有所下降,但虚拟环境由于其提供的灵活性而变得非常流行。

与网络速度一样,您可能会发现VM是实际的瓶颈,并且根据您的实际规模,直接托管应用程序就可以节省数十亿美元,而无需VM。但这对于99.9%的应用程序不会发生:它们的瓶颈在其他地方,并且由于VM的损失而造成的几微秒损失的缺点很容易通过硬件抽象和可伸缩性的优势得到补偿。


当然,我们可以说JSON响应很小,但是数量呢?我感觉像一个负载较重的网站在微服务架构中将比单片架构(唯一的网络流量是往返数据库服务器的网络流量)具有更多的网络流量。缓存可以提供帮助,但是对于实时和/或动态生成的内容,我不知道缓存能走多远。
James Mishra 2015年

@JamesMishra:我编辑了答案以解决您的问题。
Arseni Mourzenko 2015年

您的答案是完美的。您不仅回答了我能想到的所有反对意见,还回答了我没有想到的反对意见。
James Mishra'3

5
我从现实世界中获得的2美分:由非常健谈的微服务组成的系统可能纯粹由于网络阻塞而遭受性能问题。在这种情况下,缓存和基于事件流的设计是您的朋友。除了网络,CPU和内存以外,基于微服务的系统还需要在设计中纳入弹性:如果微服务关闭,会发生什么?您如何建立重试,分布式事务,自我修复,监视-我建议搜索“必须具备很高的才能使用微服务”
Sudhanshu Mishra

4
如果我错了,请纠正我,但据我所知,如果您有1Gbps网络,这意味着理论上您可以每秒通过该网络发送价值1Gb的数据。不管连接数。连接数越高,每个连接的带宽越低。因此,在不升级网络以支持更高带宽的情况下,您的实际限制为每秒26.214个响应。添加更多服务器不会增加您的网络带宽。如果单个群集可以吐出那么多的流量,则添加更多的服务器生成更多的数据将使您的网络拥挤。
塞贝(Sebbe)'17年

7

我认为您对“微型”部分的阅读过多。这并不意味着用网络服务替换每个类,而是将一个单片应用程序组件化为大小合理的组件,每个组件都处理程序的一个方面。这些服务不会互相通信,因此在最坏的情况下,您会将一个大型网络请求拆分为几个较小的网络请求。无论如何,返回的数据与收到的数据不会有很大的不同(尽管您可能会返回更多数据并将其合并到客户端中)


3
“这些服务不会互相通信。” 我想象微服务可能具有共享的依赖关系(也许是身份验证?),它们可能会分离为另一种微服务。从某种意义上说,LDAP是一种身份验证微服务,我想所有其他微服务都在与之对话。还是...认证只发生一次?每个微服务如何检查身份验证权限以防止直接对象访问攻击?
James Mishra 2015年

2
@JamesMishra很好..这取决于。当我上次使用微服务架构时,出于安全目的(但也是出于公司孤岛的原因),每个服务都完全独立于其他服务。尽管受体系结构策略控制,但身份验证的处理方式各不相同。但是,没有理由他们不能例如与auth对话,或者仅基于库进行auth。但是..我想说的是,他们不应该在自己之间传递大量呼叫,而不是他们不应该将服务本身当作客户端使用。
gbjbaanb

@JamesMishra,在这些环境中,auth通常是它自己的服务,因此每个服务都应该利用它,而不是自己进行完整的实现。
Paul

2

通过结构化代码和资源访问,使生成的系统足够灵活,可以通过配置作为整体应用程序或分布式应用程序运行。如果您将某个通用接口背后的通信机制抽象化,并且考虑到并发性来构建系统,那么对系统进行概要分析并找到真正的瓶颈之后,可以轻松地优化所有内容。


一个解释我假设@mortalapeman是什么意思的示例:您有一个Java / c#接口IProductAvailibitiy,所有IProductAvailibitiy使用者都链接到该接口。还有一个实现该接口的类ProductAvailibitiyImpl和一个使用ProductAvailibitiyImpl的ProductAvailibitiyMicroservice。可以将使用者配置为使用本地ProductAvailibitiyImpl或ProductAvailibitiyMicroservice的远程代理
k3b

2

我想从一个具有不同假设的不同行业(即分布式(实体级别)仿真)添加一个不同的角度。从概念上讲,这很像分布式FPS视频游戏。主要区别:所有玩家都共享某种状态:龙现在在哪里;没有数据库调用;为了提高速度和降低延迟,所有内容都保存在RAM中,吞吐量的相关性较低(但我想您也不能完全忽略它)。

您可以将每个参与的应用程序视为一个整体(代表一个玩家的所有方面),或者一个微服务(代表一个人群中的单个玩家)。

我的同事们一直对将单个参与的应用程序分解成更小的微服务感兴趣,这些微服务可以共享,例如损害仲裁或视线计算,这些通常捆绑在模拟中。

问题在于调度呼叫和等待请求的延迟。正如其他人所指出的,带宽无论如何都是无关紧要的。但是,如果视线计算从1微秒提高到100微秒(例如,由于所有播放器应用程序之间共享的新微服务排队),那将是一个巨大的损失(可能需要进行多次视线计算才能获得每次更新,每秒更新几次)。

请仔细考虑服务的工作方式,调用时间以及交换的数据。我们的应用程序已经不仅仅交换位置信息,它们还交换航位推算信息-我位于位置x,以速度q朝y方向行驶。在这些假设发生变化之前,我不必更新我的信息。更新次数少得多,并且延迟(虽然仍然是一个问题)出现的频率也相应降低。

因此,与其以更高的频率请求细粒度的服务,不如尝试通过以下方法降低频率:

  1. 更改请求的数据并使用本地计算
  2. 发送查询或触发器参数以进行异步响应
  3. 批处理请求
  4. 在推测时预测请求并预先准备响应(与惰性评估相反)
  5. 尽可能避免微服务调用其他微服务;显然,这使问题更加复杂。我知道这是使微服务更大并在一定程度上失误的诱因,但是微服务对延迟不是好朋友。也许只是承认并克服它。

现在,请记住检查有关系统的假设。如果您更关注吞吐量而不是延迟,或者您没有共享状态等,那么请务必在有意义的地方使用微服务。我只是说也许不要在没有意义的地方使用它们。


1

你天真的想象是对的。通常这并不重要。现代机器速度很快。微服务架构的主要优势体现在开发和维护工作以及时间上。

当然,没有规则说您不能使用共享内存,甚至不能在一个可执行文件中物理部署多个服务。只要您设计它不依赖于此即可。


CPU速度很快。记忆速度很快。SSD非常快。但是网卡,路由器和交换机是否“快速”?另一个答案是坚持的,但我不确定。
James Mishra 2015年

遇到网络速度问题绝对很容易。在旧金山运行一项服务,在阿姆斯特丹运行另一项服务,然后在悉尼使用。延迟是关键,而不是带宽。所以不要那样做。并提供合理的服务
Stephan Eggermont,2015年

1

正如很多人提到的,这与网络瓶颈无关。它更多是关于网络脆弱性。因此,第一步是避免同步通信。这比听起来容易。您所需要的只是具有正确界限的服务。正确的边界导致服务具有自治性,松散耦合性和高度凝聚力。良好的服务不需要其他服务的信息,它已经有了。优质服务的唯一交流方式是通过事件。好的服务最终也是一致的,因此没有分布式事务。

实现这种优势的方法是首先确定您的业务能力。业务能力是特定的业务责任。对整体业务价值有所贡献。所以这是我在考虑系统边界时采取的步骤序列:

  1. 确定更高级别的业务职责。会有一些。将这些服务视为您的组织应实现其业务目标的步骤。
  2. 深入研究每个服务。确定由上级服务组成的下级服务。
  3. 除了前两点,还要考虑服务通信。他们应该主要通过事件来做到这一点,只是互相通知他们的业务流程结果。事件不应被视为数据传输器。

请记住,业务服务包括人员,应用程序,业务流程。通常只有一部分代表技术授权。

这听起来有点抽象,所以可能会有一些服务边界标识示例值得关注。


0

只是增加当前答案的另一个因素。具有粗粒度的服务。您希望避免所有呼叫的延迟,因此,您进行的呼叫不会获得10个呼叫,而是获取DTO中需要的10条数据。

请记住,微服务并不像人们想象的那样微。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.