如何让不同的机器运行不同的任务?

时间:2015-02-23 07:16:54

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

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

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

任何人都可以举例说明我该怎么做?

更新: -

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

1 个答案:

答案 0 :(得分:0)

我会有五个节点: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时,结果将通过发布/订阅通知机制)。除此之外,由于工作人员可能在大师期间失败,因此船长必须在启动时进行一些清理工作。停机时间。

主算法如下:

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/节点的创建将失败,并且不会调度任何新任务。

其次,主人和工人都可能有任意失败,任何任务都不会丢失。如果工作人员失败,则在/worker中观看删除事件将触发任务的重新分配。如果主服务器出现故障且任何给定数量的工作程序在新主服务器到位之前失败,则启动过程会将任务移回/pending_tasks并发布任何待处理结果。

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