Erlang 使用键到pid机制时,处理瞬态gen_服务器状态的保存

Erlang 使用键到pid机制时,处理瞬态gen_服务器状态的保存,erlang,concurrent-programming,autosave,gen-server,Erlang,Concurrent Programming,Autosave,Gen Server,我想知道当临时gen_服务器状态与密钥关联时,如何处理它们的保存 为了将键与进程相关联,我使用了一个名为pidstore的进程。Pidstore最终会启动进程。 我给一个键和一个M,F,a到pidstore,它在全局中查找该键,然后返回pid(如果找到),或者应用MFA(必须返回{ok,pid}),用全局中的键注册pid并返回pid 我可能有很多处于非活动状态的gen_服务器,状态可能很大。因此,我设置了handle_info回调来保存数据库中的状态,然后停止进程。gen_服务器在其管理器中被认

我想知道当临时gen_服务器状态与密钥关联时,如何处理它们的保存

为了将键与进程相关联,我使用了一个名为pidstore的进程。Pidstore最终会启动进程。 我给一个键和一个M,F,a到pidstore,它在全局中查找该键,然后返回pid(如果找到),或者应用MFA(必须返回{ok,pid}),用全局中的键注册pid并返回pid

我可能有很多处于非活动状态的gen_服务器,状态可能很大。因此,我设置了handle_info回调来保存数据库中的状态,然后停止进程。gen_服务器在其管理器中被认为是暂时的,因此在再次需要它们之前不会重新启动它们

问题从这里开始:如果我在代表{car,23}的进程中的handle_info的保存步骤中调用一个进程,比如说{car,23},我将按预期返回pid,因为该进程正在保存且尚未完成。因此,我将使用gen_server:call调用我的进程,但由于进程正在停止,我将永远不会有响应(并达到默认的5秒超时)。(问题A)

为了解决这个问题,进程可以从全局注销自己,然后保存其状态,然后停止。但如果在注销后但在保存完成之前需要它,我将加载一个新进程,这个进程可以加载数据库中未更新的值。(问题B)

为了再次解决这个问题,我可以确保数据库中的加载和保存是排队的,不能同时进行。这可能是一个瓶颈。(问题C)

我正在考虑另一个解决方案:在保存之前,我的进程可能会告诉pidstore它们正忙。pidstore将保存一个繁忙进程的列表,并对这些键上的任何请求作出“繁忙”响应。 保存完成后,进程会告诉pidstore不再忙,并在询问密钥时启动新进程。(即使旧的过程还没有结束,也已经完成了保存,这样他就可以花时间独自死去)

这对我来说似乎有点混乱,但感觉更简单的做法是多次尝试从键获取Pid,而不是将每个调用包装到gen_服务器以处理可能的超时。(进程完成但仍在全局中注册时)

我对所有这些一半的问题和一半的解决方案有点困惑。您在这种情况下使用的设计是什么,或者如何避免这种情况

我希望我的信息是清晰的,请告诉我关于英语错误也


谢谢

也许您想在
genu服务器中执行save to DB部分:call
。这样可以防止在您向DB写入数据时其他呼叫传入


一般来说,听起来好像您已经创建了一个进程寄存器。如果您想在本地注册,您可能需要研究gproc(),它在这方面做得非常好。使用gproc,您可以完全按照上面所述的操作,使用密钥注册进程。如果您在
init
函数中使用gproc注册,并在写入DB时取消注册,可能就足够了。您也可以在
terminate
函数中写入DB。

现在,我决定坚持erlang的“让它崩溃”理念。如果进程在关闭时接收到消息,这些消息将不会被应答,并将触发gen_server:call/*超时


我认为在正确的位置处理此超时会很无聊,目前我还没有决定在哪里,但这是针对我的应用程序的,因此在这里没有意义。

我想回答这个问题,但不知道从哪里开始。基本上我想说的是尽量避免自己注册进程。这将导致很多复杂性。简单的start_链接将生成一个进程,当它完成时,它将让初学者知道它退出了。如果您做的不止这些,即注册流程并自行控制,您可以构建它,但维护它将是一场噩梦。使用ets和每个生成ets的gen_服务器如何?如果不满足运行条件,请查找ets并退出?我不知道你想做什么,所以我不能给你答案。@bighostkim我以为Pid表的Id在erlang应用程序中很常见!基本上,gen_服务器将检查运行条件,但可能存在竞争条件。谢谢我相信无论我使用什么(按你的建议处理电话,或处理信息),问题都是一样的:进程仍然能够在关闭时接收电话。我可以在gproc上使用我的pidstore,实际上它只是一个助手,全局似乎更容易,但我可能稍后用gen_proc替换它。谢谢你我终于找到路了。很简单:在超时时,gen_服务器保存在DB中,然后向注册表发送通知(«i am idle»)。当注册表获得此强制转换时,它调用gen_服务器synchronousy并询问«仍然空闲?»,如果是,注册表将终止它。由于在此过程中注册表无法执行anwser调用,因此如果有人希望某个特定id的pid终止,它必须等待此gen_服务器被终止,然后注册表将再次启动它。