前一段时间,我写了一篇关于从IBM BPM到Camunda的成功迁移的文章,现在我们的生活充满了幸福和愉悦的印象。Camunda并没有让我们失望,我们继续与BPM引擎保持友谊。
但是,可惜的是,卡蒙达还可能会带来令人不快的惊喜,因此有时无法获得最明显的结果。在本文中,将考虑一个案例,尽管它很简单,但事实却比乍看之下有趣且复杂得多。
我们训练猫
为了描述问题,请考虑一个综合示例。假设我们决定扩大客户群,并且需要为猫和猫服务。应该检查每个潜在客户,并可能立即提供一些东西。
我们将检查候选人的可靠性以及我们可以为他提供的服务。尽职调查和可能的服务没有任何关系-这些动作可以并行执行。在bpmn图上以示意图形式显示,如下所示:
图1.毛发服务的示意图过程
该图示意性地显示了基本步骤,派生和加入网关。
此图标描述了并行网关。并行网关是用于构建流程的并行运行部分的最简单网关。
并行网关有两种类型:
- fork-为每个分支创建一个单独的执行;
- join-等待所有传入执行完成。
执行 -表示流程实例中的“执行路径”(来自文档)。也就是说,它是流程执行的线程。
现在,让任务复杂一些。我们将按照以下方式检查和搜索服务:首先,我们检查客户端的状态,然后查看适合他的服务,然后进行一些预处理。另外,几种服务可能一次适合客户,因此我们应该能够将所有服务提供给客户。
由于我们与毛茸茸的客户合作,因此服务将是适当的:缬草,爪耙,主人的枕头和其他有用的物品。
图2.更新的蓬松客户服务图
该过程的新版本如下。该过程将并行进行可靠性检查和搜索可能的建议。搜索也并行化。在这种情况下,将执行满足相应条件的那些分支。
为了与条件并行化,将使用包含网关,该网关由以下图标指示:
包含网关是具有分支条件的并行网关。条件成立的分支将被执行。
网关有两种类型:
- fork-为每个满足条件的分支创建执行,并以与并行网关中执行相同的方式并行执行;
- join与Parallel Gateway不同,它不等待所有分支的执行,而是等待条件为真的分支的执行。
可能发生的情况是执行的检查不足,因此必须再次检查客户端。为此,请在所有检查的末尾添加一个条件,然后将其发送以重新检查,直到最开始:
图3.应该起作用的过程的最终版本
。
什么?发生了什么?
在这里,奇怪的事情开始发生。可靠性检查分支工作并到达收集并行网关。到目前为止,一切都很好。
第二分支检查物料条件,并根据结果执行相应的任务。此外,该过程在收集包容性网关的网关处停止,并且不再继续。如果您查看Coockpit(Kamunda的管理面板),那么执行将挂在收集的Inclusive Gateway和Parallel Gateway上。
图4.悬挂式维护过程
。可以说,卡蒙达的进程陷入了僵局。在这种情况下,它与并行编程和死锁理论中的死锁没有直接关系。
寻找̶̶r̶i̶k̶l̶uch̶e̶n̶i̶y̶答案
由于我对发生的事情以及为什么停止过程没有足够的了解,因此我不得不凭经验解决问题。
也许您需要Inclusive Gateway的默认分支,没有它,进程将无法正常运行?
当然很奇怪,但是尝试添加默认分支。默认分支的存在是一种很好的做法,因为否则可能无法满足单个条件,那么我们将得到一个错误。
图5.使用默认分支的服务流程
启动并获得相同的结果-该流程仍然挂在Inclusive Gateway上。
接下来是各种参数的枚举,请阅读文档,这将持续半天。在另一尝试中,该过程意外地通过了失败的任务。在搜索和调试过程中,上层分支通过客户端可靠性检查被删除的情况下,包含Inclusive Gateway的下层分支工作。也就是说,当进程仅使用Inclusive Gateway退化到较低的分支时,进程结束。
图6.退化过程
事实证明,并行网关以某种方式影响了包容性网关。这很奇怪,不合逻辑,不应该。
这怎么可能?也许您应该重新阅读有关并行和包容网关如何工作的理论。加入网关聚集所有人并继续进行该流程应该怎么办?在Internet上,他们写道,每个收集的“包含网关”(联接)都等待与进入“叉子”的号码相同的号码进入。然后突然出现了另一个问题:这个计数器到底如何工作?
你是做什么的?你如何工作的?
这个问题值得拼图游戏和智能电视节目。只有在电视节目中,他们才可以打电话给朋友。另一方面,我也可以寻求帮助。我们将称呼我们的业务流程设计师Denis。
-丹尼斯,你好!您能告诉我收集方式如何确定何时该继续进行吗?他们到处写道:“有多少钱-应该有很多钱进来。”但是他怎么认为呢?
- 很简单。 Camunda计算活动执行的次数。
- 非常感谢。现在,
考虑发生了什么。为此,再次调用初始方案,结果是:
图7.使用默认分支的挂起过程
为简单起见,我们考虑满足所有条件的情况。满足这些条件后的三个任务时,我们会有什么?
有多少活动执行?较低的三个分支,较高的一个分支,我们检查了客户的可靠性。Camunda不在乎这些是完全不同的并行分支。仅关注活动执行的数量,其中有四个,而传入的包含网关仅接收三个。
我们纠正
为了纠正这种情况,收集网关必须立即收集所有执行,然后从理论上讲,该过程将继续进行。让我们尝试保留一个而不是两个联接网关:
图8.流程的更正版本
在我看来,编辑该流程之后,看上去就不太明显了。但是它最初按计划工作。至此,任务安全地结束了,我得以推动更改并回家。
乐趣才刚刚开始
当我坐下来写这篇文章并拿出一个可以描述这种情况的流程示例时,我很失望:该流程按预期进行,没有死锁。
首先,我假设示例中的Camunda版本高于项目中的版本,而在新版本中,此问题已得到解决。但是降级Camunda却无济于事。顺便说一句,在所有示例中,都使用版本7.8.0-它与最新版本相去甚远,但这并不重要。还检查了该问题,并在当前最新版本7.13上进行了复制。
通过反复试验,问题得以解决。原始的伪造示例没有反向分支,这与我在工作场所中开发的过程不同。
事实证明,在存在反向分支的情况下,问题得以重现,并且我们陷入了一种僵局,没有反向分支,一切都会按预期进行。
案例需要理解和分析。为此,我必须查看Camunda BPM源代码。由于问题是Inclusive Gateway所致,因此在负责该元素-InclusiveGatewayActivityBehavior行为的类中寻找答案似乎是合乎逻辑的。在该过程的两个版本上运行几次调试,我意识到它是如何工作的。
如果不清楚,请参阅资源!
为了不使故事变得晦涩,基于源代码对InclusiveGateway的工作进行描述是粗略的。我们感兴趣的逻辑集中在execute方法上,在这种情况下,activatesGateway方法是最有价值的。据我了解,它检查是否可以通过InclusiveGateway。每次执行(正在运行的每个分支)都会调用execute方法。在我们的例子中,有三个这样的分支,这意味着该方法将被调用三次。
让我们看看activatesGateway方法是如何工作的。为了更好地理解,让我们为所有可执行分支命名。
图9.带有执行的流程图
根据我的理解,该方法的逻辑如下:比较到达该高速公路的处决次数和该高速公路包括的箭的数量。这种检查是在最简单的情况下执行的,当所有的Inclusive Gateway分支都被执行时,检查收集网关的逻辑是等待直到输入的执行次数等于传入的箭头数。也就是说,在最简单的情况下,执行方法的调用次数与收集网关中存在分支的次数相同,然后该过程继续进行。
在我们的例子中,此方法被调用了3次,因为传入执行的次数将从1增加到3。在最后一次调用时,传入执行的次数和传出执行的次数分别为3和4,并且我们将遵循false分支。
如果不满足条件,则检查其余执行是否属于“包含网关”。即,检查活动执行到达联接包含网关的能力。
在这里,您需要一点耐心,呼气和阅读。结局就在附近!
在activatesGateway方法的false分支中,在每次调用时,将检查尚未到达包含联接执行的那些调用,以检查达到此联接的可能性。如果至少有一次执行可以导致Inclusive Gateway,则您需要将其考虑在内,并等待其加入此联接。如果没有可以导致加入的执行,则该方法将返回true。
最有趣的部分即将到来。乍一看,最后的执行(在图中-执行1)不能导致包含网关。但是,值得一看的是参与该验证的canReachActivity方法的实现,并且此元素的这种行为的原因将变得清楚。
如果我们丢弃了所有代码细节,则在该方法内部递归调用isReachable方法,该方法逐步检查此执行是否进入收集的InclusiveGateway中。反向分支只是提供了这样的机会,可惜,尽管没有,但是应该考虑到这一点,因为我们将在所有联接之后返回。
结果,Inclusive Gateway正在等待另一个执行,它将永远不会发生。因此,我们陷入了僵局。原则上,如果放弃这些约定,则会遇到经典的死锁:在Parallel上加入join等待包含Inclusive的分支被执行,相反,在Inclusive包含Branch的分支等待Parallel执行。
下图显示了从执行开始检查Inclusive Gateway联接可用性的大致方向,该联接是通过并行分支加入Prallel Gateway的。
图10.从并行联接到包含联接
的可能路径该图显示,实际上,从并行网关联接开始,可以使用联接包含网关,并且根据Camunda BPM逻辑,有没有“圈内领先”。
在找出原因之后,不经意间出现了一个问题:这是错误还是功能?我认为这是一个错误。现在,我正在收集信息和案例,以将报告发送给Camunda团队。
问题是本地化的,这很好。但是现在呢?
实际上,现在-结论:
- 有备则无患。我们需要考虑到Camunda的这种行为来构建我们的流程。
- , . parallel join.
- Inclusive Gateway , , executions .
- , . , Parallel Gateway .
明显的简单性和清晰度有时会引起误解。这只能通过知识的积累和复制来解决。las,在解决这个问题时,我对Inclusive Join的逻辑并不了解,所以我不得不动手。我通过反复试验,打电话给朋友和调试源获得了这些知识。
从这一切可以得出一个显而易见的,远非新结论,那就是您需要了解所使用工具的工作方式。您了解得越多,此类问题就会越少。
第二个结论也很明显:您不仅需要分解代码,还需要分解过程。
在解析这种情况和撰写文章时有用的链接: