分布式计算的八个谬误 - Ably


为了更好地理解设计可靠的分布式系统所带来的挑战,我们必须参考分布式计算的谬误——架构师和开发人员可能做出的一系列错误假设:

  1. 网络是可靠的。
  2. 延迟为零。
  3. 带宽是无限的。
  4. 网络是安全的。
  5. 拓扑不会改变。
  6. 有一名管理员。
  7. 运输成本为零。
  8. 网络是同质的。

 
1.网络可靠
网络是复杂的、动态的,而且通常是不可预测的。许多原因可能导致网络故障或网络相关问题:交换机或电源故障、配置错误、整个数据中心变得不可用、DDoS 攻击等。由于这种复杂性和普遍的不可预测性,网络是不可靠的。
从基础架构的角度来看,您需要将系统设计为具有容错性和高度冗余性。
除了基础设施方面的问题,您还需要考虑由于网络故障导致的连接断开以及消息和 API 调用丢失的问题。对于某些用例(例如,实时聊天应用程序),数据完整性至关重要,并且所有消息都必须准确传递一次,以便最终用户始终(即使涉及失败)。为确保数据完整性,您的系统必须表现出有状态的特征。此外,您还需要自动重新连接和重试、重复数据删除(或幂等性 )等机制,以及强制执行消息排序和保证交付的方法。

 
2.延迟为零
在设计系统时,您应该牢记延迟是网络的固有限制。我们永远不应该假设发送数据和接收数据之间不会有延迟或零延迟。
考虑到延迟,这里还有其他几件事需要考虑:

  • 缓存。 浏览器缓存可以帮助改善延迟并减少发送到服务器的请求数量。您还可以使用 CDN 在全球多个位置缓存资源。缓存后,它们可以通过数据中心或最靠近客户端的存在点进行检索(而不是由源服务器提供服务)。
  • 使用事件驱动协议。根据您的用例的性质,您可能会考虑使用WebSockets 之类的通信协议。与 HTTP 相比,WebSockets 的往返时间要短得多(一旦建立连接)。此外,WebSocket连接保持打开状态,允许数据被服务器端和客户端之间尽快来回传递变得可用,在实时-通过HTTP请求-响应模型显著的改善。
  • 服务器性能。服务器性能(处理速度、使用的硬件、可用 RAM)和延迟之间存在很强的相关性。为防止网络拥塞和服务器超载,您需要能够(动态)增加服务器层的容量并重新分配负载。

 
3. 带宽无限
网络的容量也不是无限的(部分原因是我们对生成和消费数据的需求也增加了)。当大量数据试图流经网络,而带宽支持不足时,可能会出现各种问题:
  • 排队延迟、瓶颈和网络拥塞。
  • 导致服务质量低劣的数据包丢失,即消息丢失或无序传送。
  • 糟糕的网络性能甚至整个系统的不稳定。

有多种方法可以提高网络带宽容量:
  • 全面监测。跟踪和检查网络中的使用情况至关重要,这样您就可以快速识别问题(例如,谁或什么占用了您的带宽)并采取适当的补救措施。
  • 多路复用。协议,如HTTP / 2,HTTP / 3,和的WebSockets所有支持复用,通过允许将数据从几个来源结合并发送它通过相同的通信信道/介质提高带宽利用率的技术。
  • 轻量级数据格式。您可以使用为速度和效率而构建的数据交换格式(如JSON )来保留网络带宽。另一种选择是MessagePack,这是一种紧凑的二进制序列化格式,可以创建比 JSON 更小的消息。
  • 网络流量控制。您需要考虑使用诸如节流/速率限制、拥塞控制、指数退避等机制。

 
4. 网络安全
网络受到攻击或破坏的方式有很多:漏洞、操作系统和库中的漏洞、未加密的通信、导致数据被未经授权方访问的疏忽、病毒和恶意软件、跨站点脚本 (XSS) 和 DDoS 攻击,仅举几例(但列表是无穷无尽的)。
这里有几件事情需要考虑:
  • 威胁建模。建议使用结构化流程来识别潜在的安全威胁和漏洞,量化每个威胁和漏洞的严重性,并确定缓解攻击的技术的优先级。
  • 纵深防御。您应该使用分层方法,在网络、基础设施和应用程序级别进行不同的安全检查。
  • 安全心态。在设计您的系统时,您应该牢记安全并遵循最佳实践和行业建议和建议,例如  OWASP 的 Top 10 列表,其中涵盖了您的系统应该配备以应对的最常见的 Web 应用程序安全风险。

 
5. 拓扑不变
网络拓扑是指网络的链路和节点的排列方式和相互关联的方式。在分布式系统中,网络拓扑一直在变化。有时,这是出于意外原因或由于服务器崩溃等问题。其他时候是故意的——我们添加、升级或删除服务器。
您可以为您的特定用例选择最佳网络拓扑。请记住,您的系统需要能够快速适应网络拓扑的变化,而不会影响服务可用性和正常运行时间。考虑到这一点,您不应将任何给定节点视为不可或缺的。
 
6. 管理员一名
在非常小的系统中,或者在个人项目的上下文中,可能只有一个管理员。除此之外,在几乎所有现实生活场景中,分布式系统通常都有不止一个管理员。例如,考虑由不同团队开发和管理的许多服务组成的现代云原生系统。或者考虑使用您的系统的客户也需要他们身边的管理员来管理集成。
当你设计你的系统时,你应该让不同的管理员能够轻松(嗯,尽可能简单)来管理它。您还需要考虑系统的弹性,并确保它不会受到与其交互的不同人员的影响。这里有几件事情需要考虑:
  • 解耦系统组件。确保适当的解耦可以在计划升级导致问题或计划外事件(例如故障)的情况下提供更大的弹性。促进解耦(或松散耦合)的最流行的选项之一是pub/sub 模式
  • 使故障排除变得容易。提供对系统的可见性至关重要,以便管理员可以诊断和解决可能发生的问题。返回错误消息并抛出异常,以便管理员了解上下文并采取适当的措施来解决问题。此外,日志记录、指标和跟踪(通常称为可观察性的三大支柱)应该是系统设计的关键方面。

 
7.运输成本为零
首先,网络基础设施是有成本的。服务器、网络交换机、负载平衡器、代理、防火墙、操作和维护网络,使其安全,更不用说员工保持网络平稳运行——所有这些都需要花钱。网络越大,财务成本就越大。
除了财务,我们还必须考虑构建一个在高度可用、可靠和容错的网络上工作的分布式系统所涉及的时间、精力和难度。将这种复杂性转移到专门为此目的而设计的完全托管且经过实战测试的解决方案中通常风险更小、更简单且更具成本效益。
除了基础设施方面,还有与通过网络传输数据相关的成本。从应用层到传输层需要时间和 CPU 资源。信息需要在服务器端进行处理和序列化(编组),然后再传输到客户端,在客户端需要进行反序列化。如果您希望降低传输成本,请避免使用 XML 或基于 XML 的选项,并改用轻量级序列化和反序列化格式,例如JSONMessagePackProtocol Buffers (Protobuf)。

 
8. 网络同质化
通常,甚至您的家庭网络也不是同质的。只要有两个配置不同的设备(例如,笔记本电脑或移动设备)并使用不同的传输协议就足够了,而且您的网络是异构的。
大多数分布式系统需要与多种类型的设备集成,适应各种操作系统,与不同的浏览器一起工作,并与其他系统交互。因此,关注互操作性至关重要,从而确保所有这些组件尽管不同,但可以相互“交谈”。
在可能的情况下,使用广泛支持的开放标准协议,而不是专有协议。示例包括HTTPWebSocketsSSEMQTT。相同的逻辑适用于数据格式,其中 JSON 或 MessagePack 等选项通常是最佳选择。