Erlang / OTP模式,以确保Composite进程仅在子进程完成时才接受消息

时间:2014-12-16 12:10:36

标签: erlang otp

是否存在针对以下问题的Erlang / OTP模式/库(在我自己破解之前):

  • 在最高级别,假设有三个组件(或过程?),使得A-> B-> C,其中 - >表示发送消息给。
  • B在架构方面是一个复合过程。它由许多单元过程组成(如下面的卡其绿色所示)。有时,消息链从B1-> B2-> B3-> C开始,有时它从B1-> B4-> B5-> B6-> B3-> C。

Composite Actor

我想做的是:

  • B只能在完成所有子进程的情况下接受下一条消息,即B收到消息I1,根据消息,它将选择一个流,最后C得到消息O1。在此之前,B不应接受消息I2。这是为了确保消息的排序,使I2的O2在I1的O1之前不到达C.

1 个答案:

答案 0 :(得分:2)

这有几个名字。一个是“数据流”(如“反应式编程” - 如果你查找它就是一种夸张的流行语球),另一个是“信号模拟”(如电信号开关的模拟)。我不知道Erlang中的这个框架,因为直接实现它非常简单。

根据您想要写东西的方式,可以使消息排序问题自行处理。 Erlang保证两个进程之间的消息排序,因此只要消息在明确定义的通道中传播,就可以使这个系统范围的承诺对您有用。如果你需要比直线更有趣的信号路径,你可以强制同步通信;虽然所有Erlang消息都是异步的,但您可以在receive上的任何地方引入同步阻止。

如果您希望“B星座”将消息传递给C,但只有在其信号处理完全通过B的路径之后,您才可以创建一个信号管理器,它向B1发送消息,并阻塞直到它收到来自B3的输出,它将完成的消息传递给C并从A中检查其下一个框:

a_loop(B) ->
  receive {in, Data} -> B ! Data end,
  a_loop(B).

% Note the two receives here -- we are blocking for the end of processing based
% on the known Ref we send out and expect to receive back in a message match.
b_manager(B1, C) ->
  Ref = make_ref(),
  receive Data -> B1 ! {Ref, Data} end,
  receive {Ref, Result} -> C ! Result end,
  b_manager(B1, C).

b_1(B2) ->
  receive
    {Ref, Data} ->
        Mod1 = do_processing(Data),
        B2 ! {Ref, Mod1}
  end,
  b_1(B2).

% Here you have as many "b_#" processes as you need...

b_2(B) ->
  receive
    {Ref, Data} ->
        Result = do_other_processing(Data),
        B ! {Ref, Result}
  end,
  b_2(B).

c_loop() ->
  receive Result -> stuff(Result) end,
  c_loop().

显然我彻底简化了事情 - 因为这显然不包括任何监督的概念 - 我甚至没有解决你想如何将这些联系在一起(并且用这个小检查实时性,你会需要来生成链接它们,所以如果有什么东西死掉它们都会死掉 - 这可能正是你想要的B子集,所以你可以把它当作一个单元来处理。此外,您可能会在某处(例如在A之前/之前或在B中)需要油门。但基本上讲,这是一种通过使B块阻塞直到其处理段完成的方式传递消息的方式。

还有其他方法,比如gen_event,但我发现它们比编写处理管道的实际模拟更不灵活。至于如何实现这一点 - 我将它作为OTP主管和gen_fsm的组合,因为这两个组件代表了几乎完美的信号处理组件并行,您的系统似乎旨在模仿。

要了解gen_fsms中需要的状态以及如何将它们聚集在一起我可能会在纯粹的Erlang中以非常简单的方式原型化几个小时,以确保我实际上了解问题,然后编写我正确的OTP主管和gen_fsms。这确保我不会投入一些gen_foo行为的神殿,而不是投入实际解决我的问题(你必须在正确之前至少写两次.. )。

希望这至少给你一个开始解决问题的地方。无论如何,这在Erlang中是一种非常自然的事情 - 并且与语言和问题的工作方式非常接近,以至于它应该非常有趣。