【问题标题】:rebar3, supervisor, behaviour(application)rebar3,主管,行为(应用程序)
【发布时间】:2020-11-09 01:34:29
【问题描述】:

我有以下简单的 UDP 服务器:

  • 只接受二进制 >,

  • 否则会崩溃

     -module(server).
     -export([listen/1]).
    
     listen(Port) ->
         spawn(fun()->run_it(Port) end).
    
     run_it(Port) ->
     {ok, Skt} = gen_udp:open(Port, [binary]),
     loop(Skt).
    
     loop(Skt) ->
     receive
         {udp, Skt, _, _, Bin} ->
             case Bin of
                 <<0:32>> ->
                     io:fwrite("~p~n", [{"Good Format: ", Bin}]),
             loop(Skt)
             end
     end.
    

现在,我的对等 UDP 客户端将故意发送格式错误的数据。

我可以编写一个 case 子句来匹配任何消息并忽略任何消息 格式错误的消息。

但是,如果最终出现错误,它对我没有帮助。

我在某处读过:“不要进行防御性编程,让它崩溃,然后修复它”。

    =ERROR REPORT==== 19-Jul-2020::21:15:29.872000 ===
    Error in process <0.93.0> with exit value:
    {{case_clause,<<0>>},[{server,loop,1,[{file,"server.erl"},{line,16}]}]}

酷,它崩溃了,但我希望我的服务器现在自动重启 :-)

我读到一个名为“supervisor”的进程可以监控我的 服务器,并在检测到它死亡时重新启动它。

所以,我使用了“rebar3”,因为它在我编译时帮助了我很多 几个文件只有 1 行'rebar3 compile'。

它会自动创建一个包含 3 个文件的 /src/,但只有 2 个是 现在让我感兴趣:

  • server_app.erl
  • server_sup.erl

另外,我已经阅读了文档,但我仍然无法理解。

任何人都可以建议,或转换我的 19 行代码 server.erlserver_app.erl 并由 server_sup.erl 监督?

N.B:我不是在寻找 gen_server,我经常看到它,但我是 有义务也或仅将其转换为 gen_server 应用程序+主管可以满足我的要求吗?

提前致谢,

最好的问候,

【问题讨论】:

    标签: erlang rebar3


    【解决方案1】:

    Supervisors 是 OTP supervision 树的一部分,它处理所有重启策略等。虽然它的模块可以不使用gen_servers,但我反对它:gen_servers 为最常见的服务器操作提供了一个方便的抽象(它们处理name registeringsys 消息和其他开箱即用的好东西)。

    虽然“让它崩溃”引理在 Erlang 中很常见,但这并不意味着您不必预见代码可能面临的问题,或者您只关心幸福的情况。我不想看到任何系统由于某人的格式错误/恶意 nc -u 而崩溃。

    请记住,如果达到主管的重启限制,它也会死亡,最终到达应用程序的最高主管,这会在死亡时使 VM 崩溃。

    让我们来看看代码(很少编辑 rebar3 new app 生成的内容):

    该应用程序不需要版本:

    -module(server_app).
    
    -behaviour(application).
    -export([start/2, stop/1]).
    
    start(_StartType, _StartArgs) ->
        server_sup:start_link().
    
    stop(_State) ->
        ok.
    

    supervisor 有更多的配置,但仅此而已:

    -module(server_sup).
    
    -behaviour(supervisor).
    -export([start_link/0]).
    -export([init/1]).
    
    start_link() ->
        supervisor:start_link(?MODULE, []).
    
    init([]) ->
        SupFlags = #{strategy => one_for_all,
                     intensity => 0,
                     period => 1},
        ChildSpecs = [#{id => my_server,
                        start => {server, start_link, [12345]},
                        type => worker
                       }],
        {ok, {SupFlags, ChildSpecs}}.
    

    server.erl 需要在启动函数中进行一些修改:

    -module(server).
    -export([start_link/1]).
    
    start_link(Port) ->
        {ok, spawn_link(fun()->run_it(Port) end)}.
    
    run_it(Port) ->
        {ok, Skt} = gen_udp:open(Port, [binary]),
        loop(Skt).
    
    loop(Skt) ->
        receive
            {udp, Skt, _, _, Bin} ->
                case Bin of
                    <<0:32>> ->
                        io:fwrite("~p~n", [{"Good Format: ", Bin}]),
                        loop(Skt)
                end
    

    server.erlgen_server 类似:

    -module(server).
    
    -export([start_link/1]).
    
    -behaviour(gen_server).
    -export([
             init/1,
             handle_cast/2,
             handle_call/3,
             handle_info/2
            ]).
    
    start_link(Port) ->
        gen_server:start_link(?MODULE, Port, []).
    
    init(Port) ->
        gen_udp:open(Port, [binary]).
    
    handle_call(_Call, _From, State) ->
        {reply, ok, State}.
    
    handle_cast(_Msg, State) ->
        {noreply, State}.
    
    handle_info({udp, Skt, _, _, Bin}, Skt) ->
        case Bin of
            <<0:32>> -> io:fwrite("~p~n", [{"Good Format: ", Bin}])
        end,
        {noreply, Skt};
    handle_info(_Msg, State) -> % Messages that are not {udp, Skt, _, _, _} are discarded
        {noreply, State}.
    

    【讨论】:

    • 好吧,我确信:有时,使用“gen_server”可以让我受益于消息传递机制:“同步”、“异步”。此外,我得到了有价值的错误报告(更详细)。我编辑了“强度 = 5”,非常完美!我肯定你的回答会节省很多或 Erlanger。真的很感激!
    猜你喜欢
    • 2016-12-26
    • 2020-08-22
    • 2016-11-12
    • 2021-08-17
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 2017-04-10
    • 2014-01-07
    相关资源
    最近更新 更多