【问题标题】:How to have different machines running different task?如何让不同的机器运行不同的任务?
【发布时间】:2015-04-24 11:19:20
【问题描述】:

我有一个应用程序,其中有五个不同的任务。这五个任务中的每一个都在特定日期的不同时间段运行。我将在 4 台不同的机器上部署这个应用程序。

一般来说,我通过使用 Apache Zookeeper 在这四台机器之间选择领导者来在一台机器上运行所有这五个不同的任务。但是通过这种方法,其他三台机器将处于空闲状态,所以我在想有什么办法可以让不同的机器运行不同的任务?这意味着这四台机器中的每一台都运行这五台机器中的一些任务,但没有两台机器运行相同的任务。

谁能举例说明我将如何做到这一点?

更新:-

我在不同任务之间没有任何依赖关系。它们都是相互独立的。

【问题讨论】:

  • 不同任务之间是否存在依赖关系?
  • @OferLando 不,不同任务之间没有依赖关系。它们相互独立。
  • 看看我写的这个项目。它做类似的事情。您也许可以直接使用它或作为示例:github.com/NirmataOSS/workflow

标签: java distributed-computing apache-zookeeper distributed-system leader


【解决方案1】:

我将有五个节点:pending_taskscompleted_tasksrunning_tasksworkersqueuespending_tasks 是保存任务的节点,包括新任务和由于工作节点故障而重新触发的任务。 completed_tasks 保存已完成任务的详细信息。 running_tasks 保存分配给工作人员的任务。在 PoC 实现中,我曾经使用 XML 编码的 POJO 来存储任务的详细信息。 pending_taskscompleted_tasksrunning_tasks 中的节点都是持久节点。

workers 包含代表可用工作人员的临时节点。鉴于它们是短暂的,这些节点表示工作器中的故障。 queuesworkers 直接相关:queues 中的每个节点在workers 中都有一个节点。 queues 中的节点用于保存分配给每个工人的任务。

现在,您需要一位大师。主人负责三件事:i)监视pending_tasks的新任务; ii) 观察workers 注册新的queues,当新工人到达时,并在工人失踪时将任务放回pending_tasks; iii) 在completed_tasks 中发布任务的结果(当我做这个 PoC 时,结果将通过发布/订阅通知机制)。除此之外,master 必须在启动时进行一些清理,因为在 master 停机期间,worker 可能会失败。

主算法如下:

at (start-up) {
  for (q -> /queues) {
    if q.name not in nodesOf(/workers) {
      for (t -> nodesOf(/queues/d.name)) {
        create /pending_tasks/t.name
        delete /running_tasks/t.name
        delete /queues/d.name/t.name
      }
      delete /queues/d.name
    }
  }

  for (t -> nodesOf(/completed_tasks)) {
    publish the result
    deleted /completed_tasks/c.name
  }
}

watch (/workers) {
  case c: Created => register the new worker queue
  case d: Deleted =>  transaction {
    for (t -> nodesOf(/queues/d.name)) {
      create /pending_tasks/t.name
      delete /running_tasks/t.name
      delete /queues/d.name/t.name
    }
    delete /queues/d.name
  }
}

watch (/pending_tasks) {
  case c: Created => transaction {
    create /running_tasks/c.name
    create persistent node in one of the workers queue (eg, /queues/worker_0/c.name)
    delete /pending_tasks/c.name
  }
}

watch (/completed_tasks) {
  case c: Created =>
    publish the result
    deleted /completed_tasks/c.name
}

worker算法如下:

at (start-up) {
  create /queue/this.name
  create a ephemeral node /workers/this.name
}

watch (/queue/this.name) {
  case c: Created =>
    perform the task
    transaction {
      create /completed_tasks/c.name with the result
      delete /queues/this.name/c.name
      delete /running_tasks/c.name
    }
}

关于我何时想到此设计的一些注释。首先,在任何给定时间,都不会运行针对相同计算的任务。因此,我根据已进行的计算来命名这些任务。因此,如果两个不同的客户端请求相同的计算,则只有一个会成功,因为只有一个能够创建 /pending_tasks 节点。同样,如果任务已经在运行,/running_task/ 节点的创建将失败并且不会分派新任务。

其次,master 和 worker 都可能出现任意故障,不会丢失任何任务。如果一个worker失败了,/worker中的delete事件的监听会触发任务的重新分配。如果在新的 master 就位之前一个 master 失败并且任何给定数量的 worker 失败,启动过程会将任务移回/pending_tasks 并发布任何待处理的结果。

第三,我可能已经忘记了一些极端情况,因为我无法再访问这个 PoC 实现了。我很乐意讨论任何问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    相关资源
    最近更新 更多