如何让 Cadence 工作流程拒绝信号

How to have a Cadence workflow reject signals

除了 MaximumSignalsPerExecution 之外,还有其他方法可以让工作流程拒绝信号吗?

基本上我有一个工作流,在它超时之前会定期像新的一样继续。但是,如果它在继续作为新信号之前不断收到大量信号,它最终会超时并丢失一些信号。我可以将 MaximumSignalsPerExecution 设置得更低,这样它会在超时前拒绝信号,但理想情况下我想要一些可以在工作流级别配置的东西。

我正在测试一些更糟糕的情况,在这些情况下会出现流量高峰并且工作流每秒会收到多个信号。

首先,回答您的问题:不幸的是,没有任何其他限制可以阻止发送信号的数量。不过,我不确定那会有多大用处。 signalstartsignalwithstart API 是 Cadence 用户调用的最关键的 API 之一,因为这些 API 在 Cadence 中持久化数据。我们通常会尽量保持这些 API 的高可用性,以便我们可以接受并保留这些请求附带的数据。否则,客户端将不得不有一个回退数据存储来保存被 Cadence 拒绝的请求,或者只是将失败传播到他们的上游。

MaximumSignalsPerExecution 限制的主要好处是保护 Cadence 数据库免受单个工作流执行的无限增长。我不建议仅仅为了改进一个用例而使用它。

信号与ContinueAsNew之间的竞争是一个相对常见的问题。我有一些想法来解决这个问题,但我认为由于优先事项的竞争,我们无法很快完成。与此同时,我认为最好的办法是为您的工作流程设定正确的期望。以下是您在设计工作流程时应牢记的两个原则:

  • 尽管 Cadence 在并发工作流的数量方面横向扩展得很好,但它在 per-workflow 的基础上扩展得不是很好。原因是 cadence 服务器为每个工作流获取锁并将每个数据库更新作为昂贵的事务进行,以便提供幕后所需的所有一致性保证以确保工作流安全。我推荐的经验法则是:设计您的工作流,使其每秒生成的事件不超过 10 个,包括接收到的信号。当您超过该限制时,您将开始为特定工作流触发锁争用,导致延迟增加和超时,即使系统的其余部分相当 healthy/idle.
  • decision tasks(即您的工作流对事件做出反应并决定下一步的时间)应该非常快,以毫秒为单位。这将增加工作流程周围的一切快速移动而不会相互阻塞的机会。

在您的情况下,您应该研究以下想法(如果您还没有的话):

  • 想想如果有硬性限制(比如每秒 5 个),如何减少每个工作流程的信号数量。也许您可以通过启动许多类似的工作流程而不是仅仅一个工作流程来解决这个问题,然后随机发送一个信号来在它们之间分配负载
  • 确保您的决定尽可能快,尤其是在处理信号和尝试以新方式继续时。
  • 如果您尝试在收到信号后安排任何工作(即 activity 等),请尝试将其放入列表并将其作为输入传递给下一个 运行 的工作流作为输入,因此新的工作流 运行 执行之前 运行 跳过的信号处理工作。

除了 Emrah 的详细回答和想法之外,我还想添加更多想法来使用 Cadence 工作流程本身来解决这个问题。这些想法不需要你使用任何其他技术(DB/MessageQueue/etc)

  • 取决于你想用什么条件来拒绝新信号,可能你可以使用 search attribute to record some states of the workflow. In workflow, use upsertSearchAttribute API to update the condition. Then before sending any signals, use DescribeWorkflowExecution API 来读取搜索属性并用它来决定你是否应该发送信号
    • 上面的想法有点误用了搜索属性。因为我们没有使用属性来搜索任何东西。理想情况下,我想使用“备忘录”来完成它,但“备忘录”在今天的工作流程中是不可改变的。这是 open issue 我想允许像更新 SA 一样更新备忘录。
    • 因为这个想法不需要“搜索”工作流程。所以即使您不为搜索属性启用 AdvancedVisibilty,您仍然可以这样使用它。
  • 或者,您可以使用 query 方法代替 SA。但是查询比描述工作流要重得多。 DescribeWorkflowExecution 在 Cadence 上几乎没有成本,而且速度非常快。所以我建议在这种情况下使用 SA。
  • 从长远来看,Cadence 应该支持在接受信号之前拒绝条件。已经有一些想法可以做到这一点。但设计和实现起来非常复杂。名称是 TBD,有人称它为“Update API”,有人称它为“SignalWithQuery”,但本质上,我们想提供一个同步的 API 来发送查询并获得响应。