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

时间:2015-12-17 12:09:56

标签: javascript node.js settimeout message-queue raft

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

例如,我们有一个公司表,如果修改了名称地址字段,我们会触发Zapier挂钩。< / p>

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

如果要在不同的实例之间保持状态,从基础结构的角度来看,应该考虑一些锁定机制,例如Redis。 每当你想要运行Zapier调用时,如果没有锁定激活,你在Redis上设置一个,所有其他调用都不会被锁定,因为只要setTimeout回调运行,你就会禁用锁定。 请注意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);

  }

}