在什么条件下(如果有),查询两个服务器并且仅消耗最快的响应是一种好习惯吗?


12

我问过什么是SO上现在被社区删除的问题,为什么有人会使用javascript的问题Promise.race,而一个高级用户则对此发表了评论:

如果您有两个计算某个值的服务,则可以并行查询它们,并使用第一个返回的值,而不是查询一个,等待失败,然后查询第二个。

我已经在冗余和这种用例上进行了全面的搜索,但是我什么也找不到,而且从我的POV中来看,如果不打算使用响应,只向服务器/服务添加工作负载绝不是一个好主意。


玩具示例:不是总是使用quicksort,而是复制数据,将其发送到quicksort,mergesort,heapsort等。等等。您不必检查输入以查看是否为病理案例对于任何这些的,因为它不会是一个pathalogical情况下,所有的
Caleth

Dean和Barroso的论文《规模的尾巴》称这种方法为“对冲请求”。它还讨论了控制错误率和延迟的长尾变化的几种相关方法的优缺点。
丹尼尔·普里登

第二个“服务器请求”可能是假的。它可能只需要5秒钟,然后返回一个占位符响应。这会使您在实际请求上超时。
user253751'18年

订购Lyft,然后订购Uber。以先到者为准。
user2023861

以此类推@ user2023861,虽然一个驾驶员毫无意义地驶向您的位置,但他/她本可以接受另一个请求
-Adelin

Answers:


11

我认为这更多是经济学问题。但是,这是工程师应该能够做出的判断。因此,我在回答。

我将答案分为四个部分:

  • 风险管理
  • 策略
  • 费用
  • 直觉

风险管理

因此,有时您的客户端无法从服务器获得响应。我将假定这不是由于程序错误引起的(否则解决方案是要修复它,因此请执行此操作)。相反,这一定是由于您无法控制的偶然情况造成的。

但并非超出您的了解。您必须知道:

  • 它多久发生一次。
  • 它有什么影响。

例如,如果失败和重试仅发生在大约2%的时间,则可能不值得解决。如果发生这种情况的时间大约是80%,那么...取决于...

客户需要等待多少时间?以及如何将其转化为成本...您看到的是,在常规应用程序中的延迟很小,可能没什么大不了的。如果这很重要,并且您有实时应用程序或在线视频游戏,那么这将使用户拒之门外,您可能最好投资更多或更好的服务器。否则,您可能会发出“正在加载”或“正在等待服务器”消息。除非延迟真的很大(大约几十秒),否则即使对于常规应用程序也可能太大。


策略

正如我上面所说,解决这个问题有多种方法。我将假定您已经具有try-fail-retry循环工具。所以,让我们看看...

  • 放入加载消息。它便宜,有助于保留用户。
  • 并行查询。可以更快,仍然可以失败。将需要冗余服务器(可能很昂贵),将浪费服务器时间和网络流量。
  • 并行查询以稳定速度更快的服务器并从那里开始使用它。可以更快,仍然可以失败。将需要冗余服务器(可能会很昂贵),不会浪费那么多服务器时间和网络流量。

现在,请注意我说这些仍然可能失败。如果我们假设对一台服务器的查询有80%的失败机会,那么对两台服务器的并行查询有64%的失败机会。因此,您可能仍然需要重试。

选择较快的服务器并继续使用它的一个额外好处是,较快的服务器也不太可能由于网络问题而出现故障。

这提醒我,如果您能弄清请求失败的原因,请这样做。即使您无法防止失败,它也可以帮助您更好地管理情况。例如,您是否需要在服务器端提高传输速度?

多一点:

  • 在全球范围内部署多台服务器,然后按地理位置选择服务器。
  • 在服务器端进行负载平衡(专用计算机将处理所有请求,并将它们重新发送到您的服务器,您可以在其中进行并行处理,或者采用更好的平衡策略)。

谁说您只需执行其中一项?您可以放置​​一条加载消息,查询分布在整个仓库中的多个服务器以选择更快的服务器,并仅在此之后使用它,然后在发生故障的循环中重试,并使这些服务器中的每一个成为具有负载平衡功能的计算机集群。为什么不?好吧,费用...


费用

有四个费用:

  • 开发成本(通常非常便宜)
  • 部署成本(通常很高)
  • 成本运行时间(取决于应用程序类型和业务模型)
  • 失败的代价(可能很低,但不是必须的)

您必须平衡它们。

例如,假设您每个满意的用户赚取大约1美元。您每天有3000个用户。请求失败约有50%的时间。并且当请求失败时,有2%的用户离开时不付费。这意味着您每天损失(3000 * 50%* 2%)30美元。现在,让我们说开发新功能将花费您100美元,部署服务器将花费您800美元-而忽略了运行时成本-这意味着您将获得((100 + 800)/ 30 ) 30天。现在,您可以检查预算并做出决定。

不要认为这些代表现实的价值,我出于数学上的考虑而选择它们。

附录:

  • 记住,我也忽略了细节。例如,您的部署成本可能很少,但是要花CPU时间,因此您需要考虑这一点。
  • 如果您不将其数据包浪费在冗余请求中,则某些客户可能会感激。
  • 改善您的产品可能有助于带来自然的广告。
  • 不要忘记机会成本。您是否应该开发其他产品?

事实是,如果您以固定成本的角度考虑问题,则可以估算所考虑策略的成本,然后使用此分析来确定。


直觉

凭经验培养直觉。我不建议每次都进行这种分析。有人这样做,没关系。我建议您对此有所了解,并为此建立直觉。

此外,在工程方面,除了我们从实际科学中获得的知识外,我们还在实践中学习并编写了哪些行之有效的指南。因此,明智的做法是了解最新技术水平……尽管有时您需要查看所在区域之外的地方。

在这种情况下,我将看在线视频游戏。它们具有加载屏幕,具有多个服务器,它们将根据延迟选择一个服务器,甚至可以允许用户切换服务器。我们知道这可行。

我建议这样做,而不是在每个请求上浪费网络流量和服务器时间,还要注意即使使用冗余服务器,也会发生故障。


2
我认为我不需要说这句话,但这是一个很好的答案:)我知道我会在前10行接受它,但是我给了您机会,仍然可以失败并继续阅读它。您没有
阿德林

9

如果客户端的时间比服务器上的时间更有价值,这是可以接受的。

如果客户需要快速准确。您可以证明查询多个服务器是合理的。如果收到有效答案,则取消请求非常好。

当然,咨询服务器的所有者/经理总是明智的。


为什么需要取消请求?当然这是主观的。
JᴀʏMᴇᴇ

@JᴀʏMᴇᴇ,那是内在的妄想。我曾经使用无法清除队列的系统,并且在队列已满时确实崩溃了(是的,它是专业软件)。
Toon Krijthe

4

此技术可以减少延迟。服务器响应时间不确定。从规模上看,可能至少会有一台服务器显示较差的响应时间。因此,任何使用该服务器的人都将具有较差的响应时间。通过提交给多个服务器,可以减少与性能不佳的服务器通信的风险。

成本包括额外的网络流量,浪费的服务器处理和应用程序复杂性(可以将其隐藏在库中)。通过取消未使用的请求或在发送第二个请求之前短暂等待,可以降低这些成本。

这是一张纸另一张纸。我记得也曾读过一篇Google论文,了解其实现方法。


2

我大多同意其他答案,但是我认为这在实践中应该很少见。我想分享一个更常见,更合理的示例,说明您何时使用Promise.race(),几周前我碰巧使用了它(嗯,相当于python)。

假设您有一长串任务,有些可以并行运行,有些必须在其他任务之前运行。您可以开始所有不依赖项的任务,然后使用来等待该列表Promise.race()。第一个任务完成后,您就可以启动任何依赖于该第一个任务的任务,然后Promise.race()再启动新列表,再结合原始列表中未完成的任务。继续重复直到完成所有任务。

注意Javascript的API并不是为此而设计的。这几乎是最低限度的工作原理,并且您必须添加很多胶合代码。但是,我的意思是,类似这样的功能race()很少用于冗余。当您实际上想要所有承诺的结果,但又不想等待所有承诺完成后再采取后续行动之前,它们就在那里。


问题是,至少使用Javascript的Promise.race,您实际上在每次执行race方法时就开始执行任务。它不会在未完成的任务上执行,而是新的任务集,而无需考虑之前执行的操作(除非您在任务级别实现该逻辑)。否则,原始列表将被遗忘,仅保留第一个任务的返回值
Adelin

1
Javascript中的承诺会在new Promise调用时立即启动,而在调用时不会重新启动Promise.race()。一些promise实现是懒惰的,但是渴望更加普遍。您可以通过在控制台中创建登录到控制台的Promise进行测试。您会立即看到它的日志。然后把那个诺言传递给Promise.race()。您会看到它不再记录。
Karl Bielefeldt

啊,那是真的。但是afaik除了promise.race以外,其他promise的其余承诺的返回值都被遗忘了。race–
Adelin

这就是为什么我说API的设计不是理想的。您必须将原始任务集存储在某个地方的变量中。
Karl Bielefeldt

1

除了技术方面的考虑之外,您还可能希望在实际业务模型中使用这种方法。

这种方法的变体在广告实时出价中相对常见。在此模型中,发布者(广告空间提供商)将要求广告商(广告提供商)针对特定用户的展示出价。因此,对于每一个这样的印象,你会查询每个广告主的订阅,发送的印象细节查询到每个广告商提供的端点(或者,运行作为自己的服务器上的端点由广告客户提供的脚本),赛车所有这些请求直到超时(例如100毫秒),然后采用最高出价,而忽略其他请求。

有助于减少客户等待时间的一个特定变体是使发布者允许出价的最低目标值,这样,超过该值的第一个广告客户出价将被立即接受(或者,如果没有一个出价超过该值)该值,将采用最大值)。因此,在这种变体中,第一个到达的查询可能会获胜,而另一个则会被丢弃,即使它们同样好甚至更好。

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.