【问题标题】:How to provide extra information to supervisor when restarting a child in erlang OTP?在erlang OTP中重新启动孩子时如何向主管提供额外信息?
【发布时间】:2015-01-22 22:41:39
【问题描述】:

假设我有一个主管sup 监督一些工人,当一个工人开始时,它会用一些名字注册自己,比如worker_1worker_2 等。当worker_N 崩溃并由@987654326 重新启动时@,如何将新创建的进程注册为worker_N,即如何让worker的名字在重启后存活?

How to restart child with custom state using Erlang OTP supervisor behaviour? 没有回答,因为我只想要名字,也许有解决办法。

【问题讨论】:

    标签: erlang


    【解决方案1】:

    您可以通过在init 中调用register(Name, self()) 并在那里将Name 作为参数传递来让worker 在启动时注册自己。这是跨节点全局的,因此注册的进程无关紧要。

    但是

    看起来您正在动态创建原子,因为您想在任何地方使用已注册的进程。这是一个非常常见的错误——但有希望!

    与其动态创建原子来命名每个存在的子工作人员,不如先考虑几件事:

    • 您不需要全部命名。工人的工作有限 描述(如果他们没有,你有更大的问题),他们是 几乎总是与他们的资源、调用者或生成器相关联, 谁已经认识他们了。
    • 您确实需要为它们命名(但实际上,您可能不需要),因为它们 表示大型系统的具体元素,例如 游戏、聊天频道、跟踪受害者的 Twitter 提要等。 以不同的方式命名它们,保留[{Key, Value}] 的摘要 其中[{AnyTerm, Pid}]。这使您可以通过以下方式了解有关该过程的更多信息 查看它的名称​​和可以让你的系统的全局空间免于 私人工人碎屑。

    还有更多...

    如果您正在命名进程整数,您要么犯了无数 Web 开发人员在使用关系数据库时犯的相同错误(使所有内容都具有整数主键),要么您正在处理 不需要名称的工作人员。

    如果您确实需要命名它们(它确实发生了),请考虑使用global 模块(它可以让您将任何进程命名为任何您想要的术语,并且这些名称可以在所有节点上使用——神奇!),“进程组”在pg2 模块中,或gproc(为处理这个确切问题而编写的库,还允许您使用任何您想要命名进程的术语)。

    个人笔记

    如果您发现自己处于生成动态原子似乎是个好主意(无论出于何种原因)的情况下,您应该始终停止您正在做的任何事情,并认真思考您正在做的事情。这是因为生成原子强烈表明你做错了。试着找出你为什么如此努力地与系统作斗争——Erlang 不应该那样工作。

    无论是在我自己的代码中遇到过,还是在其他人的工作中看到过,这种情况都表明存在一种更清洁、更 Erlangy 的做事方式,如果我发现一切都会变得更容易不管怎样,而不是在我正在处理的复杂逻辑的大结中添加更多层。好消息是,积累 Erlang 习语很快而且很难忘记,因为回想起来它们通常非常有意义(几乎总是你发现在发现可接受的解决方案之前你正在重新发明轮子 - 并且最后以“啊,伟大的思想都一样”的感觉结束)。

    【讨论】:

    • 这是迄今为止我在 stackoverflow 上读到的最佳答案。感谢您提供这些详细信息。我使用坐标作为名称,每个工人都做与该坐标相关的工作,然后通过(x, y, z) ! some_msg 将结果传递给其他一些工人,这就是为什么我要命名我的工人。这可以描述为“1-worker-1-coordinates”,如果我不命名它们,那么它应该是“1-worker-many-coordinates”,对吧?在后一种情况下,它的常见模式是什么,我应该编写一个调度程序来告诉工作人员它应该处理哪个消息?
    • 我在编写的一个教学项目中遇到了相同的情况(我将项目从幼稚的非 OTP 演变为生产 OTP 风格)。最初,我在“父级”中保留了一个注册表(它是一个主管,但不是一个合适的主管)并回复{From, Ref, {get_pid, LocID}}LocID 可以是任何东西,在这种情况下是 {X,Y,Z},但这是偶然的。稍后我将使用global (erlang.org/doc/man/global.html) 和global:send(LocID, Msg) 代替LocPid ! Msg,稍后我将演示pg2 和gproc。
    • @NotanID 另外,请注意,随着时间的推移,Destination ! Message 形式的“裸”发送调用开始消失,并被封装在模块接口 API 后面。在项目的一开始,这可能很麻烦,但是一旦你对你正在尝试做的事情有一个明确的想法,将你的消息调用移动到模块 API 后面可能是一个真正的救命稻草——模块之间的状态数据访问也是如此(不要不要盲目地在标题中包含记录定义!)。这是“位置管理器”的(非常非 OTP)示例:github.com/zxq9/erlmud/blob/master/erlmud-0.1/locman.erl#L38
    • @NotanID 另外,不要将那里的代码视为佳能。它被刻意写成尽可能单一(但不是错误)。随着时间的推移,代码库将变得更加 Erlangy——这就是演示的重点。 gproc 基本上为你提供了这个 {K,V} 类型的 Pid 目录服务,预先打包好使用。很酷。无论如何,一次手写是探索这个想法的好方法,并且会让其他关于 global、pg2 和 gproc 所做的事情对你更有意义。
    • 哦,伙计,zxq9.com/archives/983zxq9.com/erlmud/html/index.html,正是我需要的。
    猜你喜欢
    • 2017-05-02
    • 2012-11-11
    • 2017-09-24
    • 2012-06-22
    • 2012-11-13
    • 2023-03-16
    • 2011-07-26
    • 1970-01-01
    • 2011-09-04
    相关资源
    最近更新 更多