仍然沿用Corda Services的趋势,我还有其他一些技巧可帮助您的CorDapp顺利工作。 这次,我们将重点关注使用trackBy从服务内部启动流以及如果您不小心可能会引起的离散问题。
这应该是一个相对简短的职位,因为我可以依靠之前的职位: Corda Services 101和Corda Services的 异步流程调用 。 在Corda Services的“异步流”调用中找到的内容与此帖子非常相关,并且将包含此帖子中未包含的其他信息。
这篇文章适用于Corda Open Source和Enterprise。 撰写本文时的版本为Open Source 3.2
和Enterprise 3.1
。
trackBy简介
trackBy
允许您编写在包含指定类型的状态的事务完成时执行的代码。 无论将它们作为输入还是输出,代码仍将触发。
在这里,您可以决定要执行的操作。 也许很简单,例如记录已收到状态的日志。 或者,也许更有趣的事情,例如启动新流程。 此用例对该功能非常有意义。 节点接收到新状态或消耗新状态后,便可以启动代表流程中下一个逻辑步骤的新流程。
此外,还有trackBy
两个版本。 一是我一直提到的trackBy
,可以在CorDapp中使用。 另一个vaultTrackBy
是使用RPC从节点外部调用的。
本文中提出的问题仅在CorDapp版本trackBy
。 因此,在本文的其余部分中,我们将不包括vaultTrackBy
。
这个离散的问题是什么?
僵局。 当我这样说时,它不是很离散。 但是,它的发生方式相当微妙,需要对将要解决的问题有一个很好的了解。 如前所述,此问题与Corda Services的异步流调用中详细介绍的问题非常相似。 此外,当我在项目中遇到此问题时,R3再次大喊大叫以诊断此问题,我确信他们会解决这个问题。 在此之前,如果您遇到相同的问题,这篇文章应该可以省去一些麻烦。
我将引用我在上一篇文章中写的内容,因为它的解释仅缺少关于该帖子的一点。
“ Flow Worker队列负责执行Flow执行的顺序,并在Flow添加和完成时填充并为空。 该队列对于协调节点内流的执行至关重要。 当涉及到多线程Flows本身时,这也是痛苦的根源。”
“我为什么要谈论这个队列? 好吧,我们需要格外小心,不要将无法完成的流程填满队列。
怎么会这样 通过在正在执行的流程中启动流程,然后流程等待其完成。 直到队列的线程池中的所有线程都遇到这种情况,这才不会引起问题。 一旦发生,它将使队列陷入僵局。 没有流程可以完成,因为它们都依赖于排队的多个流程来完成。”
那标志着我的复制面的终结。 我会继续说这句话,实际上,我建议您通读Corda Services的异步流调用,以对该主题进行彻底的解释。
这与trackBy
有什么关系? 从服务调用trackBy
将在Flow Worker线程上运行每个可观察的事件。 换句话说,每个事件都占据队列中的一个位置。 从此处启动Flow将向队列添加另一个项目,并挂起当前线程,直到Flow完成。 它将一直保留在队列中,直到那个时候。 如果您遇到的情况是队列中的所有位置都由可观察的事件而不是实际的流程所占据,那么我为您提供了一个词。 僵局。 这与我之前详细介绍过的情况完全相同,只是从不同的震中开始。
从好的方面来说,解决方案是小菜一碟(这句话从何而来?)。
解决问题的部分
现在您知道了问题所在。 将“中断”版本更改为可避免死锁的版本,仅需要几行。
让我们看一些与导致我踏上这个地雷的代码非常相似的代码:
每当节点收到新的MessageState
时,此Service就会使用trackBy
启动新的Flow。 由于前面提到的所有原因,此代码可能会死锁。 我们不知道什么时候发生,或者是否会发生。 但是,可以。 因此,我们可能应该在问题解决之前对其进行整理。
下面的代码将做到这一点:
我添加了一些注释以使更改更清晰,因为仅添加了几行。
所有这些更改所做的就是在新线程上启动Flow。 然后,这将允许当前线程结束。 请记住,这很重要,因为该线程保持在队列中的某个位置。 允许它结束,为接下来发生的事情腾出空间。 它是来自trackBy
还是Flow的另一个可观察事件。 不要紧。 只要释放线程,就不会由于该代码而发生死锁。
从此线程释放您
请花一点时间来欣赏我在本节标题中所做的双关语的荣耀。 也许不是很好,但我仍然为此感到自豪。
总之,在Corda Service中使用trackBy
非常适合根据已保存到节点的信息来启动新流程。 但是,从trackBy
观察开始新流程时,您需要小心。 这是由于可观察到的保持在Flow Worker线程上,因此是队列中的一个点。 如果吞吐量达到更高的数量,则可能会出现节点死锁的风险。 您可能会遇到以下情况:队列被所有线程都阻塞,这些线程都在等待流完成,但队列中没有实际的流。 通过将Flow调用移动到与可观察线程不同的线程上。 您可以释放队列中曾经保留的位置。 现在,您的trackBy
代码不再可能导致死锁。
这篇文章中使用的代码可以在我的GitHub上找到 。
如果您认为这篇文章有帮助,可以在Twitter上@LankyDanDev关注我,以跟上我的新文章。
翻译自: https://www.javacodegeeks.com/2018/10/starting-flows-trackby.html