erlang節(jié)點名稱注冊(erl_epmd)與cookie管理(auth)

net_supkernel中繼 dist_ac(distribution applicationcontroller)后啟動的監(jiān)控者(supervisor),除了前文提到的net_kernel(提供節(jié)點互聯(lián))之外,還有erl_epmd(提供epmd名字注冊)auth(提供cookie管理)。

拓?fù)鋱D如下:

            | - erl_epmd
net_sup --- | - auth
            | - net_kernel

本文主要說的是 erl_epmdauth

1. epmd(名字注冊)

epmd相關(guān)的配置參數(shù)和環(huán)境變量:

名字 數(shù)據(jù)類型 備注
start_epmd true / false 在開啟節(jié)點時候是否開啟epmd,默認(rèn)true
epmd_module atom epmd模塊,默認(rèn)是erl_epmd
epmd_port int 向指定端口注冊Node
ERL_EPMD_ADDRESS string epmd 監(jiān)聽地址
ERL_EPMD_PORT int epmd端口號,注意:同一個集群使用同一個端口號,默認(rèn)4369
1.1 如何設(shè)置epmd端口
$ epmd
$ export ERL_EPMD_PORT=Port

$ erlang node
$ erl -epmd_port Port -name ......

% erl_epmd.erl
get_epmd_port() ->
  case init:get_argument(epmd_port) of
    {ok, [[PortStr | _] | _]} when is_list(PortStr) ->
      list_to_integer(PortStr);
    error ->
      ?erlang_daemon_port
  end.

環(huán)境變量ERL_EPMD_PORTvm參數(shù) epmd_port配合起來使用,可以在同一個機(jī)器上部署多個集群

# 演示了同一臺機(jī)器部署2個集群
$ 集群一,epmd端口號4000
$ export ERL_EPMD_PORT 4000
$ erl -epmd_port 4000  -name abc@127.0.0.1
(abc@127.0.0.1)1> erl_epmd:names().
{ok,[{"abc",9591}]}

$ 集群二,epmd端口號5000
$ export ERL_EPMD_PORT 5000
$ erl -epmd_port 5000  -name abc@127.0.0.1
(abc@127.0.0.1)1> erl_epmd:names().
{ok,[{"abc",21309}]}
1.2 注冊名稱過程
% erl_epmd.erl
% 由 net_kernel 發(fā)起
handle_call({register, Name, PortNo, Family}, _From, State) ->
  case State#state.socket of
    P when P < 0 ->
      % 只有當(dāng)沒有注冊的時候,才允許注冊,換句話說,一個Node只會調(diào)用一次
      case do_register_node(Name, PortNo, Family) of
        {alive, Socket, Creation} ->
          S = State#state{socket = Socket,port_no = PortNo,name = Name},
          {reply, {ok, Creation}, S};
        Error ->
          {reply, Error, State}
      end;
    _ ->
      {reply, {error, already_registered}, State}
  end;

do_register_node(NodeName, TcpPort, Family) ->
  Localhost = open(TcpPort) % 連本地的epmd
  case Localhost of
    {ok, Socket} ->
      % Socket 正確連上epmd
      Name = to_string(NodeName),
      Packet = ...
      case gen_tcp:send(Socket, Packet) of
        ok ->
          % 發(fā)送注冊包,等待回包
          wait_for_reg_reply(Socket, []);
        Error ->
          close(Socket),
          Error
      end;
    Error ->
      Error
  end.
  
wait_for_reg_reply(Socket, SoFar) ->
  receive
    {tcp, Socket, Data0} ->
      ...
    {tcp_closed, Socket} ->
      {error, epmd_close}
  after 10000 ->
    % 默認(rèn)10秒超時,并且不能修改。
    gen_tcp:close(Socket),
    {error, no_reg_reply_from_epmd}
  end.

注意點:

  • 每個節(jié)點只能注冊一次
  • 注冊結(jié)束之后保存注冊連接(Socket)作為后續(xù)與epmd的交互媒介

2. auth(管理cookie)

auth 功能比較單一,就是保存本地的cookie, 相關(guān)的vm參數(shù)如下:

名字 數(shù)據(jù)類型 備注
nocookie - 主動不設(shè)置cookie
setcookie string 設(shè)置節(jié)點cookie

設(shè)置cookie流程

init_cookie() ->
  case init:get_argument(nocookie) of
    error ->
      case init:get_argument(setcookie) of
        {ok, [[C0]]} ->
          C = list_to_atom(C0),
          #state{our_cookie = C, ...};
        _ ->
          % 從$HOME/.erlang.cookie讀取cookie
          case read_cookie() of
            {error, Error} ->
              error_logger:error_msg(Error, []),
              %% Is this really this serious?
              erlang:error(Error);
            {ok, Co} ->
              #state{our_cookie = list_to_atom(Co),
                other_cookies = ets:new(
                  cookies,
                  [?COOKIE_ETS_PROTECTION])}
          end
      end;
    _Other ->
      #state{our_cookie = nocookie,other_cookies = ...}
  end.

  1. 如果vm設(shè)置nocookie 參數(shù),直接忽略cookie,否則第二步
  2. 如果vm設(shè)置setcookie參數(shù),則保存該 cookie, 否則第三步
  3. $HOME/.erlang.cookie 讀取cookie

如上如果要設(shè)置一個集群的cookie,有2種方式:

  1. 顯示使用setcookie參數(shù)(erl -setcookie Cookie),缺點是cookie容易被同一機(jī)器上別的用戶發(fā)現(xiàn)
  2. 使用$HOME/.erlang.cookie文件,保密性強(qiáng)。

3.總結(jié)

erl_epmd,auth是節(jié)點互聯(lián)的基礎(chǔ)。通過對機(jī)制的深入理解,讓我們對集群的配置有更多控制權(quán)。

4. 參考文獻(xiàn)

  1. https://github.com/erlang/otp/blob/master/lib/kernel/src/kernel.erl
  2. https://github.com/erlang/otp/blob/master/lib/kernel/src/erl_distribution.erl
  3. https://github.com/erlang/otp/blob/master/lib/kernel/src/auth.erl
  4. https://github.com/erlang/otp/blob/master/lib/kernel/src/erl_epmd.erl
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容