在erlang OTP中重新启动子级时,如何向主管提供额外信息?

在erlang OTP中重新启动子级时,如何向主管提供额外信息?,erlang,Erlang,假设我有一个主管sup管理一些工人,当工人开始工作时,它会用一些名字注册自己,比如worker\u 1,worker\u 2,等等。。当worker\N崩溃并通过sup重新启动时,如何将新创建的进程注册为worker\N,即,如何让worker的名称在重新启动后仍然有效 没有给出答案,因为我只需要名称,可能有一个解决方案。当工作进程启动时,您可以让它在init中调用register(name,self())并将name作为参数传递给它。这在整个节点上是全局的,所以注册过程是什么并不重要 但是 看

假设我有一个主管
sup
管理一些工人,当工人开始工作时,它会用一些名字注册自己,比如
worker\u 1
worker\u 2
,等等。。当
worker\N
崩溃并通过
sup
重新启动时,如何将新创建的进程注册为
worker\N
,即,如何让worker的名称在重新启动后仍然有效


没有给出答案,因为我只需要名称,可能有一个解决方案。

当工作进程启动时,您可以让它在
init
中调用
register(name,self())
并将
name
作为参数传递给它。这在整个节点上是全局的,所以注册过程是什么并不重要

但是

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

< >不要动态地创建原子来命名每个存在的童工,首先考虑一些事情:

  • 你不需要所有的名字。工人的工作有限 描述(如果他们没有你有更大的问题),他们是 几乎总是与他们的资源、调用者或产卵者联系在一起, 谁已经认识他们了
  • 您确实需要命名它们(但实际上,您可能不需要),因为它们 表示大型系统的具体元素,例如 游戏、聊天频道、跟踪受害者的推特订阅等。 通过保留
    [{Key,Value}]
    其中
    [{AnyTerm,Pid}]
    。这可以让您通过以下方式了解更多有关流程的信息: 查看其名称,并保持系统的全局空间不受影响 私人工人碎屑
还有更多…

如果您将流程命名为整数,那么您要么犯了无数web开发人员在使用关系数据库时犯的相同错误(使所有内容都有一个整数主键),要么处理的是不需要名称的工作人员

如果你真的需要他们命名(发生),考虑使用<代码> Global 模块(它可以让你说出任何你想要的术语,所有的名字都可以在所有节点上使用——魔术!),在“代码> PG2< /Cult>模块中的“进程组”,或者(一个专门为处理这个问题而编写的库,还允许您使用任何想要命名进程的术语)

个人备忘

如果你发现自己处于一个生成动态原子似乎是个好主意的情况下(无论出于何种原因)无论你在做什么,你都应该停下来,认真思考你在做什么。这是因为产生原子强烈地表明你做错了。试着去发现你为什么要如此努力地与系统抗争——Erlang不应该以这种方式工作


无论我在自己的代码中遇到过什么情况,还是在其他人的工作中看到过什么情况,这类事情都表明存在一种更干净、更环保的做事方式,如果我发现了这种方式,而不是在我正在处理的复杂逻辑中添加更多的层,一切就会变得更容易。好消息是总结Erlang习惯用法很快,而且很难忘记,因为回顾起来它们通常很有意义(几乎总是你发现自己在发现公认的解决方案之前就在重新发明轮子——最后会有一种“啊,伟大的人想法相似”的感觉).

这是我迄今为止读到的关于stackoverflow的最好答案。感谢这些详细信息。我使用坐标作为名称,每个工人都做与该坐标相关的工作,然后通过
(x,y,z)!some_msg
,这就是为什么我要命名我的工人。这可以描述为“1-worker-1-coordinate”,如果我不说出它们的名字,那么它应该是一个“1-worker-many-coordinates”,对吗?在后一种情况下,它的常见模式是什么,我应该写一个调度器来告诉工人它应该处理哪条消息吗?我在写的一个教学项目中有一个相同的情况(我将一个项目从幼稚的非OTP发展为生产OTP风格)最初,我在“父级”中保留一个注册表(它是一个主管,但不是一个合适的)并响应
{From,Ref,{get_pid,LocID}}
LocID
可以是任何东西,在这种情况下它是
{X,Y,Z}
,但这是偶然的。稍后我将使用
global
()和
global:send(LocID,Msg)
代替
LocPid!Msg
,稍后我将演示pg2和gproc。@另外,请注意,随着时间的推移,“裸体”发送形式为
Destination!Message
的调用开始消失,并被包装在模块接口API后面。在项目的一开始,这可能会很麻烦,但一旦您确定了要做什么,将消息调用移到模块API后面可能会是一个真正的救命稻草——mo之间的状态数据访问也是如此dules(不要盲目地在标题中包含记录定义!)。下面是一个“位置管理器”的(非常非OTP)示例:@NotanID另外,不要将那里的代码视为canon。它被有意地编写为不规则的(但没有错)随着时间的推移,代码库将变得更加Erlangy——这就是演示的全部要点。gproc基本上提供了这个{K,V}为您键入Pid目录服务,预打包使用。非常酷。无论如何,手工编写一个目录服务是探索这个想法的好方法,并将使有关global、pg2和gproc的其他内容在以后对您有明显的意义。哦,伙计,这正是我需要的。