在当今世界,有很多理由编写并发软件。提高性能和吞吐量的愿望导致了许多不同的异步技术。然而,所涉及的技术通常很复杂,并且是许多细微错误的根源,特别是当它们需要共享可变状态时。如果不需要共享状态,那么这些问题可以通过更好的抽象来解决,称为期约(https://en.wikipedia.org/wiki/Futures_and_promises)。这些允许程序员将异步函数调用连接在一起,等待每个调用返回成功或失败,然后再运行链中的下一个适当的函数。
使用本文中描述的设计模式,程序员可以构建线程或进程的协作系统,这些系统简单易于理解,因为有期约期约期约提供的抽象。由于
期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。在基本设计中,请求工作者的每项工作都会创建一个在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。来处理该工作。依赖性工作会挂钩到这个期约期约
并等待它完成,然后再开始。如果再次请求该工作,新的工作者只需挂钩到当前的
期约期约链,并与其他所有工作者一起等待结果。简而言之,
期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。抽象了锁定,并允许程序员专注于上层模式。通过限制系统可以达到的可能组合的集合,处理所有可能的情况变得简单、显而易见,并消除了并发程序固有的最大类别的错误。
开发人员经常需要跨机器集群、进程或线程分发工作。这些分布式系统通常需要复杂的代码来确保只有一个工作者完成每项工作,并且不会遗漏任何工作,但当某些工作依赖于先前的工作时,情况只会变得更糟。这些部分如何同步自身?工作者何时等待另一个工作者完成工作,何时自己承担工作?
本文展示了如何轻松解决这些问题和其他问题,而无需复杂的管理系统,而是使用在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。来创建一个状态机,从而极大地简化了情况。与许多分布式编程算法不同,这些工作者协同工作以确保它们中只有一个完成一个唯一的工作单元,并与需要该数据的工作者进行通信。这消除了对工作者管理的需求,可以扩展到任意大的集群,并且最重要的是,使编写和理解代码变得容易。在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。在这种系统中可以完成什么类型的工作?答案是,碰巧的是,任何可以唯一命名的工作。使用一个简单的数据结构来保存工作的名称和相关的在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。可以防止任何未完成的工作被重新处理,并允许新的请求挂钩到未完成的期约。这简单而容易地在工作者之间进行协调,并为程序员提供了一个简单的 API,无论他们喜欢哪种语言,只要该语言支持 Promise。该 API 在服务器软件中特别有用,因为工作可以是 Web 服务器的请求处理、MapReduce 算法的函数计算或数据库查询。
无论涉及什么都不重要,只要所有工作者都使用相同的命名方案。最简单的解决方案是哈希每项工作以获得这个唯一名称。这对于大多数类型的工作都是有效的,因为它们很容易表示为文本并进行哈希处理。期约当工作者收到其中一项工作时,它会从系统内的中央授权机构请求一个
期约
期约期约,它会根据它收到的在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约的哪一端来检查是否应该开始处理。否则,它只需挂钩适当的函数,以便在期约完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到期约。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。在更大的规模上,如果系统设计需要多个服务器或进程,则每个进程中的中央授权机构必须在它们之间实现某种同步。程序员必须注意确定他们在这种分布式系统的 CAP 频谱中的位置。在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。没有,也不能解决分布式共识问题,实际上,甚至不知道正在发生这种协调。最好的解决方案是将问题抽象到一个专门为此设计的外部源。如果工作可以多次完成而不会造成损害,那么可用且分区容错的算法将是最合适的。在可能的情况下,没有工作者会重复工作,但在边缘情况下不会发生灾难。对于只能发生一次的工作,应使用一致且分区容错的算法来代替锁定机制。在网络分区的情况下,某些工作者将无法处理,但这是保持一致性的权衡。。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。完成此系统后,程序员不再需要担心如何同步的细节。他们可以将精力投入到他们实际需要解决的问题上。什么是 Promise?由于在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约提供了此算法使用的核心功能,因此理解它们非常重要。从根本上讲,一个期约什么是 Promise?有两个组成部分,本文中称为。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。deferreds完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到.
和什么是 Promise?futures。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。。。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。deferred什么是 Promise?是一个完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到.
期约完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到的输入端,即实际发生工作的部分。一旦工作完成,什么是 Promise?deferred什么是 Promise?就会使用结果进行解析。如果发生错误,什么是 Promise?deferred在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。可以使用错误进行拒绝。在任何一种情况下,
future都是。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。期约什么是 Promise?的输出端,它接收结果。在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。Futures完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到可以链接,因此一个什么是 Promise?future完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到可以充当其他
期约期约的什么是 Promise?future什么是 Promise?。每个。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。future期约接受两个函数:成功和失败。如果
期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。被解析,则使用结果值调用成功函数。如果什么是 Promise?期约期约被拒绝,则使用错误调用失败函数。如果一个
future期约没有定义适当的函数,则值会冒泡到任何附加的
。由于
future什么是 Promise?可以附加错误函数,因此它们不需要在成功函数内部具有错误处理代码。这避免了回调的问题之一:将错误处理与成功处理代码混合在一起。但是,如果错误是可恢复的呢?那么就有一个只有错误函数的中间
future。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。。如果发生错误,它可以修复错误,然后解析自身。这将调用下一个。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。future。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。的成功函数。如果没有发生错误,则中间函数只需将值传递给下一个什么是 Promise?future
的成功函数。在任何一种情况下,都会发生适当的处理。这允许什么是 Promise?future在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。作为 try/catch 块的异步等效项工作。
Promise期约还具有另一个特性,这与它们的回调表亲不同:在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约
可以使用。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。期约。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。进行解析或拒绝。当这种情况发生时,一个新的。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。future
被插入到链中,位于任何等待当前步骤的。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。future什么是 Promise?之前。此功能的一个重要用途是失败函数中的恢复代码。通过使用在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约完成时解析。一旦实际处理请求的工作者完成,它就会将数据发送到解析它,获取数据的失败尝试可以再次尝试,而其他等待数据的
不知道发生了错误。通过使用这种技术,开发人员可以将编程任务的各个部分封装到松散耦合的原子函数中,这些函数的排序很容易理解,如图 1 所示。在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。状态期约必须运行其成功函数或失败函数,中央授权机构维护的整个系统只有几个必须理解的状态。首先,是等待在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。。一旦工作者开始处理,
期约。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。可能会永远处于等待状态,因为其关联的在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。deferred在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。尚未解析。为了解决这个问题,中央授权机构应该向工作者公开一个函数,工作者可以使用该函数接收定期通知作为健康脉冲。即使使用这些定期通知,系统仍然可能发生丢失。中央授权机构应扫描当前未完成的工作,并拒绝任何等待时间过长的。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。期约
。这将触发链中的重试代码。。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。一旦
使用工作结果进行解析,它必须开始遍历附加到它的
future期约链。在这些步骤中的任何一步中,都可能发生错误。幸运的是,。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。期约future将抛出的异常转换为对下一个 catch 函数的调用。将这些错误传递到链中意味着它们将在 catch 函数中得到正确处理,或者传递给外部调用者。这可以防止工作静默失败或以不良状态完成。。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。最后,如果工作结束,一切都按预期运行,并且系统已处理请求。由于期约期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。抽象到这三个状态,因此可以在代码中以显而易见的方式处理每个状态。这可以防止许多困扰分布式系统的细微错误。
基本算法设计。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。该协作算法的核心遵循五个简单步骤,如图 2 所示。
1. 工作单元获得一个约定的名称,以便对同一工作的多个请求获得相同的。这会通知所有其他工作者结果,并允许它们并行处理其完成处理程序。该系统使程序员可以轻松编写并发处理系统,而无需陷入锁定或复杂的无锁算法的细节中。期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。。如果没有约定的命名方案,则没有工作者可以知道另一个工作者是否已经在处理该工作。在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。2.期约是从当前正在运行的请求的哈希表中请求的。如果不存在
,则创建一个
期约在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。,添加到哈希表,并返回给请求者。如果已经存在
期约
,则返回关联的在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。future期约。更改每种情况下返回的内容允许工作者知道它应该开始处理还是只是等待。
3. catch 函数附加到在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约
。如果发生错误,此 catch 函数会重试,运行原始函数。通过这样做,新的尝试将捕获并再次尝试。这允许无限重试,或者通过跟踪重试尝试的计数,该函数可以向上移动到链中而不是恢复。由于每个处理此在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。期约
4. 要对输入执行的工作被附加,以便在数据到达后可以进行处理。多个工作者是否同时执行工作应该无关紧要,因为它们的期约future在许多语言中都可用,因此这种设计模式可以在最合适的语言中实现,甚至可以在每个进程中使用多种语言实现。并行完成。此外,通过返回此futurefuture
,工作可以链接到前面完成的工作片段。
期约
,那么它应该在完成工作处理后解析
deferred
。如果在处理过程中发生故障,则应拒绝带有错误的
,这将通知所有工作者他们应该重试。
当工作由小的可组合部分组成时会发生什么?递归请求每个工作部分意味着
期约
可以通过前一个部分的
future
来解析。这会将小的部分链接在一起,工作者会向后遍历它需要的链,直到找到开头或它可以利用的另一个工作者。由于每个
future
都是异步的,因此工作者不再需要持有它,并且当