Erlang:编写任务调度程序应该以什么监督树结束?

时间:2011-03-23 15:34:37

标签: erlang task behavior scheduler supervisor

主要是出于教育目的,我正在尝试编写一个任务(任务是一个open_port({spawn_executable,Command}))调度程序。

我最终得到了像

这样的树
        supervisor
        |        |
scheduler        receiver
gen_event        gen_event
                     |
                supervisor
                     |
                dispatcher
                gen_server
                     |
                supervisor
                |    |   |
             task1  ... taskN

换句话说:

  1. 顶级主管启动调度程序和接收程序并确保它们将存活
  2. 接收者启动中层主管
  3. 中层主管启动调度员并确保它将存活
  4. 调度员启动底层主管
  5. 底层主管根据请求启动任务,并确保在出现错误时重新启动任务

  6. 在任何时候,调度程序都准备接受带有时间戳的任务,该任务应该在

    执行

  7. 当满足时间戳时,它会通知某个event_manager
  8. 然后,
  9. 接收方将由同一事件管理器通知,并通过中间主管将消息传递给调度员
  10. 调度程序有一些业务逻辑,这就是为什么它不是无状态的,例如,某些任务不能同时执行
  11. 当满足所有条件时,调度员将任务传递给底层主管,确保执行任务直到获得正常退出或绕过一些thresold
  12. 底层主管返回一条消息,然后向上传递给某个事件管理器
  13. 和调度程序最终收到此消息,从队列中删除任务或重新排队或其他内容
  14. 问题是:

    1. 我是否正确使用行为?
    2. 结构不是太复杂了吗? (但是,将来系统将会分发。)
    3. 有没有办法将接收器+中间主管和调度员+底层主管组合在两个模块中,而不是四个同时实现4个行为?
    4. 或者有没有办法将接收器+调度员+底层管理器组合在一个模块中,无需中间管理员,同时实现gen_event + gen_server +管理员行为?
    5. 我是否错误地考虑过OO语言中的接口或多继承行为? (这让我问问题3和4。)
    6. 提前致谢。

      P上。 S. IMO,一方面,结构太复杂;另一方面,这样的结构允许我将其任何块分布(例如,许多调度器到一个接收器,一个调度器到多个接收器,许多调度器到多个接收器,每个接收器有许多调度器,甚至每个调度器的许多底层监控器) - 每一层都有自己的监督政策)。复杂性和可扩展性之间的平衡点在哪里?

1 个答案:

答案 0 :(得分:1)

我建议更简化你的设计:

        supervisor
        |        |
 dispatcher      |
 +scheduler      |
                 |
            supervisor
            |    |   |
         task1  ... taskN

单独的调度程序将事件发送给启动任务等的调度程序,即使根据分发情况,也没有太大的收获。

调度程序调度程序可能很简单地在定时器模块的帮助下完成,并且可以是gen_server。 Timer可以发送可以在handle_info回调中处理的消息,也可以调用gen_server的api函数。

您还可以使用超时功能在下一个间隔之后唤醒gen_server,这会更加简单,因为您在添加新“任务”时不必担心取消计时器。

然后,调度程序/调度程序调用{​​{1}}来添加工作任务。

可以轻松添加分发:调度程序/调度程序可以位于与第二级主管不同的节点上。任务启动功能可以进一步分发,也可以使用pool模块进行负载均衡。

回答你的五个问题:

  1. 我怀疑你在不需要的地方使用gen_event,但由于不需要模块本身,因此可以通过删除它们来轻松修复。 gen_event是指如果您希望能够在一个事件源上注册多个处理程序,那么您将以1:1的比例使用它。监督树通常建立在主管是其他主管的直接子女的基础上。

  2. 是的,它过于复杂,看起来有点像你用OO语言做的那样,表现力较弱。只是为了准备一个可能的分发它没有必要。像Erlang这样的函数式语言中的重构比你想象的要容易得多。因此,如果您确定需要,请启动简单和拆分功能。

  3. 3 + 4。看到我完全不同的建议。

    1. 它不像OO那样。 OTP中的行为只是将通信模块隐藏在通用模块中的回调模块。
    2. 即使我使用简单的结构,也有很多灵活性(由Erlang带给你),因为如果你想拥有多个调度程序,你可以使用rpc来调用主管。您可以使用pool自动加载平衡任务分配。并且调度程序部分可以很容易地与调度程序分开(然后在顶层管理程序下),您可以将更多的公共状态与调度程序分开。