我只是在重新阅读Leslie Lamport的经典论文《 时间,时钟和分布式系统中的事件排序》 。 本文的大部分内容讨论如何管理逻辑时钟而不是物理时钟排序的事件。 当然,自从撰写本文以来,关于如何充分利用同步良好的物理时钟,也进行了许多有趣的学术和实践工作(显然,所有的魔术都在于定义“良好同步”的含义以及如何实现)。 )。
无论如何,我最震惊的是他在论文结尾处写的一段话:
失败问题是一个棘手的问题,任何详细讨论都超出了本文的范围。 我们将观察到,整个失败的概念仅在物理时间的背景下才有意义。 没有物理时间,就无法将失败的进程与仅在事件之间暂停的进程区分开。 用户只能因为等待响应的时间太长才知道系统“崩溃”。
那段有很多智慧!
从编写串行,同步算法到编写异步,分布式系统的过程中,至关重要的是要了解在简化的界面下可以从哪里抽象出复杂性,以及在什么地方需要接受要处理的根本不同的东西。 按照约定调用本地同步接口时,您会在一定时间内获得成功或失败响应。 当您将消息发送到分布式组件时,它本质上是异步的。 即使存在基础连接的抽象和声称可以保证成功或失败响应的协议,但在物理级别上,您只是在发送和接收离散消息。 最终,您需要准备仅仅由于某些事情花费了“太长时间”而认识到失败。 重要的是,“失败”可能是未能接收到您的消息,未能处理您的消息或仅仅是未能提供响应(这导致了幂等的概念,但这是一个单独的主题)。
但是“太长”是什么?
在这一点上,您似乎只有两种选择-您使用一些超时(根据某些历史数据流进行硬编码,配置或动态计算),或者将有关“过长”的决定传播(平移)到较高级别的系统,通常最终是用户。 然后,用户根据自己的紧迫性,不耐烦或对某些带外信号可能存在的系统状态的外部理解,来决定何时放弃或明确重试(也许他们了解到,来自该物业角落的无线信号)总是粗略的)。
我们使用了几种常见的机制来解决这一基本挑战。
最通用的策略是尝试减少系统中不同代理之间的预期响应时间差异。 这不会改变问题的总体形状,但实际上可以使用更紧密的超时范围,并为通过系统提供反馈和持续的进度流提供了机会,以便为具有挑战性的“过长”评估提供输入。
响应时间存在根本差异(例如,您可能要求分布式代理执行一系列非常简单的事情或非常困难的耗时的事情)时,一种常见的技术是使代理做出简单的“得到”响应一旦请求被接受并排队。 那时,分布式代理处于处理该请求的显式可发现状态,并且稍后将移至反映请求完成的显式可发现状态。 以这种方式对交互进行建模的优势在于,它反映了整个系统中正在发生的事情的真实性。 Microsoft为适合Microsoft OneAPI设计模式的REST API开发的指南建议对完成时间差异较大的请求采用这种通用方法。
此技术的一种不太有效的变体是提供有关操作进度的持续反馈(通过移动经过明确的不同状态的反馈,提供一些持续的活动指示或明确的进度百分比)。 在此方法的基础上,您具有相同的基本系统结构-代理在显式系统状态中移动。
我的经验是,最好使用第一种技术对系统进行显式建模。 您专注于对系统本身建模,而不是对系统上执行的操作进度进行建模。 它通常需要更多的初始基础架构,但会导致系统组件之间的耦合松散。 尤其是在我们的多设备环境中,随着来来往往的代理以及具有间歇性和变化连接性的代理,将系统建模为不同的可发现状态,而不是使用显式的1–1通讯和反馈通道来使系统更加健壮和灵活。
仅在物理时间的上下文中故障才有意义的这种观点是我们构建的系统的真正“物理”发挥作用的那些关键位置之一。 我们生活在爱因斯坦的宇宙中,我们建立的系统需要反映这一点。
From: https://hackernoon.com/what-is-too-long-4e15418f10ce