从多个 Node.js 个实例访问相同的 setTimeout() 实例

Access same setTimeout() instance from multiple Node.js instances

如果在我们的数据库中修改了某些特定数据,我们的 API 需要将数据发送到 Zapier。

例如,我们有一个 company table,如果 nameaddress 字段被修改,我们触发了 Zapier 钩子。

有时我们的 API 在几分钟内收到多个更改请求,但我们不想多次触发 Zapier 挂钩(因为它非常昂贵),所以我们调用 setTimeout()(并覆盖现有的 setTimeout)每个修改请求,延迟 5000ms

它工作正常,即使我们在这个 5000ms 期间收到来自客户端的大量修改请求,也没有多次 Zapier 挂钩调用。

现在 - 由于我们的流量在增长 - 我们想在某些负载均衡器后面设置多个 node.js 实例。

但在这种情况下,不同的 Node.js 实例不能使用 - 并覆盖 - 相同的 setTimeout 实例,这会导致很多无用的 Zapier 调用。

你们能帮助我们,如何解决这个问题 - 同时保持可扩展性?

如果你想在不同的实例之间保持状态,从基础设施的角度来看,你应该考虑一些锁定机制,比如 Redis。 每当你想 运行 Zapier 调用时,如果没有锁处于活动状态,你在 Redis 上设置一个,所有其他调用都不会被触发,因为它被锁定,每当 setTimeout 回调 运行s,你禁用了锁定。 请注意,Redis 可能会成为 SPOF,我不知道您在哪里托管服务,但这可能是需要考虑的重点。

编辑:

Redis 上的锁可能引用了您要更新的最后一条信息。因此,在第一个请求中,您将数据设置为保存在 Redis 上,等待 5 秒,然后更新。如果在该时间范围内进行了任何修改,它将存储在 Redis 上,这样您只会每隔 5 秒更新一次,不过您需要在此处添加一些额外的逻辑。示例:

function zapierUpdate(data) {

  if (isLocked()) {

    // Locked! We will update the data that needs to be saved on the
    // next setTimeout callback
    updateLockData(data);

  } else {

    // First lock and save data.
    lock(data);
    // and update in 5 seconds
    setTimeout(function(){
      // getLockData fetches the data on Redis and releases the lock
      var newData = getLockData();
      // Update the latest data that might have been updated.
      callZapierNow(newData);
    },5000);

  }

}