Erlang:主管中的 gen_server 不会在最后已知状态重新启动

Erlang: gen_server in supervisor does not restart at the last known state

我在 Erlang 工作,我的主管是这样的:

-module(a_sup).
-behaviour(supervisor).

%% API
-export([start_link/0, init/1]).

start_link() ->
  supervisor:start_link({local,?MODULE}, ?MODULE, []).

init(_Args) ->
  RestartStrategy = {simple_one_for_one, 5, 3600},
  ChildSpec = {
    a_gen_server,
    {a_gen_server, start_link, []},
    permanent,
    brutal_kill,
    worker,
    [a_gen_server]
  },
  {ok, {RestartStrategy,[ChildSpec]}}.

还有一个 gen_server 看起来像这样:

-module(a_gen_server).
-behavior(gen_server).

%% API
-export([start_link/2, init/1]).

start_link(Name, {X, Y}) ->
  gen_server:start_link({local, Name}, ?MODULE, [Name, {X,Y}], []),
  ok.

init([Name, {X,Y}]) ->
  process_flag(trap_exit, true),
  io:format("~p: position {~p,~p}~n",[Name, X, Y]),
  {ok, {X,Y}}.

move(Name, {DestX, DestY}) ->
   gen_server:cast(Name, {move, {DestX, DestY}}).

handle_cast({move, {DestX, DestY}}, {X,Y}) ->
  {noreply, {DestX, DestY}}.

move(Name, {DestX, DestY})基本上是把Name的位置移动到新的位置。现在,当我启动主管然后 gen_server 并尝试使用 erlang:exit(Pid1, die). 使其中一个子进程崩溃时,进程崩溃并重新启动,如预期的那样,但它从最初启动的原始位置开始( X,Y) 而不是最后已知的位置 (DestX, DestY)。我想知道 gen_server 是否可以以一种方式存储状态,当进程重新启动时,它会在最后一个已知位置而不是原始位置恢复?

gen_server 本身有一个 volatile 状态,从某种意义上说(正如你在问题中所描述的那样)一旦服务器死机它就会消失。 要保留状态,您需要使用一些外部机制,例如:

  • an ets table 在这里你保存所有服务器的状态索引...比如...服务器名称或其他东西。
  • persistent_term,同样,在一个非常大的地图中索引信息,其中键是您的服务器的 ID……或者使用多个术语,每个服务器一个。

但是,如果您最终使用了这些解决方案中的任何一个,现在就值得考虑是否需要服务器。如果他们唯一的职责是管理某些状态……一旦该状态安全地存储在其他地方,您可能需要考虑直接在那里管理它,而不是通过服务器进程来执行相同的操作。