【问题标题】:Getting a sibling process in Elixir在 Elixir 中获取兄弟进程
【发布时间】:2015-08-21 17:21:21
【问题描述】:

我有一个 Elixir/Erlang 进程树:

parent (Supervisor)
├── child1 (GenServer)
└── child2 (GenServer)

child1(一个 DB 客户端)拥有 child2 需要使用的信息。将 Supervisor 进程的引用传递给 child2 以使 child2 始终具有对 child1 的有效引用的好方法是什么?我是否只需要重组我的应用程序,让 child2 由 child1 监督?

【问题讨论】:

    标签: erlang elixir erlang-otp


    【解决方案1】:

    最简单的方法可能是使用本地别名注册child1child2。您可以在启动 GenServer 时通过传递 name 选项来执行此操作:

    defmodule Child1 do
      use GenServer
    
      def start_link do
        GenServer.start_link(__MODULE__, [], name: __MODULE__)
      end
    end
    

    在这种情况下,由Child1 模块支持的进程将在本地以别名Child1 注册。然后,如果您想向它发送消息,您可以使用该别名而不是 PID

    defmodule Child1 do
      # ...
    
      def get_data do
        GenServer.call(__MODULE__, :get_data)
      end
    
      def handle_call(:get_data, _from, state) do
        {:reply, extract_data_from_state(state), state}
      end
    end
    

    如果您想要一个更复杂的解决方案,例如可以注册许多相同类型的不同进程,请查看gproc library

    【讨论】:

      【解决方案2】:

      我不使用 Elixir,但我使用 Erlang,我认为我的答案在这两种情况下都是有效的。

      如果您的 child1 类型的进程是永久的,并且数量固定,那么最简单的解决方案是注册它们(game_server,event_server,...)

      但是如果他们有短暂的生命,他们的数量是不固定的,或者会存在许多相同类型的进程(例如游戏中的玩家进程)我建议使用另一个组织:

      • 顶级主管启动 2 个进程,一个服务器和一个主管。
      • 至少,服务器将维护所有活动“child1”进程的列表,这些进程具有允许访问它们的某些特征(玩家 ID ...)。通常它还会使用主管进程来启动、杀死……“child1”进程。
      • supervisor 是一个简单的工厂,它将使用 simple_one_for_one 策略创建和监督“child1”。

        parent (Supervisor) ├── child2 (GenServer) └── Client_supervisor(Supervisor) ├── Client_server(registered GenServer) └── Client_factory(registered Supervisor) ├── Child1(GenServer) ├── Child1'(GenServer) └── ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-17
        • 2013-01-06
        相关资源
        最近更新 更多