erlang集羣IP及端口管理

erlang集羣是依靠epmd維護的,epmd是erlang集羣節點間端口映射的守護進程,負責維護集羣內的節點連接,提供節點名稱到IP地址及端口的解析服務。

epmd 自定義端口號

epmd端口配置

默認情況下,epmd綁定在4369端口。但是,端口固定的話,容易遭受攻擊,可能導致新節點的認證失敗而無法啓動,或無法加入集羣。或者要在一臺機器上部署不同的erlang集羣,希望不會互相干擾。
epmd -daemon -port 5000
如果想用調試模式啓動 epmd,使用 epmd -d -port 5000

另外,epmd通常伴隨着erlang節點啓動時自動啓動,無須手動處理,所以,這裏也可以通過修改erl啓動參數以達到自動調整epmd端口。
erl -name [email protected] -epmd "epmd -port 5000 -daemon" 

節點啓動配置

epmd端口改變時,erlang節點需要顯式指定epmd端口信息。
windwos下啓動方式
1、設置環境變量ERL_EPMD_PORT
C:\>set ERL_EPMD_PORT=5000
C:\>erl -name [email protected] 
注意了, 以上命令端口號(這裏是5000)前後不能留有空格。
2、設置erlang啓動參數
erl -name [email protected] -epmd_port 5000

linux下啓動方式
1、設置環境變量ERL_EPMD_PORT
ERL_EPMD_PORT=5000 erl -name [email protected]
2、設置erlang啓動參數
erl -name [email protected] -epmd_port 5000

這兩種方式是等價的,erlang啓動時會做以下處理:
// erlexec.c
static void add_epmd_port(void)
{
    char* port = get_env("ERL_EPMD_PORT");
    if (port != NULL) {
	add_args("-epmd_port", port, NULL);	
    }
}
其中,epmd_port在erl_epmd模塊被用到,完成epmd連接。
%% 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.
	    
%%
%% Epmd socket
%%
open() -> open({127,0,0,1}).  % The localhost IP address.

open({A,B,C,D}=EpmdAddr) when ?ip(A,B,C,D) ->
    gen_tcp:connect(EpmdAddr, get_epmd_port(), [inet]);
	
%% 註冊節點名稱和端口
do_register_node(NodeName, TcpPort) ->
    case open() of
	{ok, Socket} ->
	    Name = to_string(NodeName),
	    Extra = "",
	    Elen = length(Extra),
	    Len = 1+2+1+1+2+2+2+length(Name)+2+Elen,
	    gen_tcp:send(Socket, [?int16(Len), ?EPMD_ALIVE2_REQ,
				   ?int16(TcpPort),
				   $M,
				   0,
				   ?int16(epmd_dist_high()),
				   ?int16(epmd_dist_low()),
				   ?int16(length(Name)),
				   Name,
				   ?int16(Elen),
				   Extra]),
	    wait_for_reg_reply(Socket, []);
	Error ->
	    Error
    end.

epmd相關問題

限制指定IP的節點加入集羣

epmd -port 5000 -address 127.0.0.1 -daemon
這樣,如果節點名字不是 [email protected],將無法啓動,或加入集羣。


如何殺掉epmd進程

epmd獨立於erlang節點,在所有節點關閉後還會繼續存在,有時候可能需要殺掉epmd進程。
epmd  -kill

設定節點連接監聽端口

節點啓動時,會啓動一個tcp socket,用於監聽並處理其他節點的連接請求,但是,這個端口號是隨機的,有時候我們需要定義防火牆規則,就要對端口範圍做一些限定。
通過修改erlang啓動參數即可設定,方法如下:
erl -name [email protected] -kernel inet_dist_listen_min 9100 -kernel inet_dist_listen_max 9200
看下這兩個參數是怎麼被使用的?
%% inet_tcp_dist.erl 

listen(Name) ->
	%% 啓動本地節點監聽socket
    case do_listen([{active, false}, {packet,2}, {reuseaddr, true}]) of
	{ok, Socket} ->
	    TcpAddress = get_tcp_address(Socket),
	    {_,Port} = TcpAddress#net_address.address,
	    %% 註冊節點名稱和端口
	    case erl_epmd:register_node(Name, Port) of
		{ok, Creation} ->
		    {ok, {Socket, TcpAddress, Creation}};
		Error ->
		    Error
	    end;
	Error ->
	    Error
    end.

do_listen(Options0) ->
    %% 獲取端口範圍
    {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of
		       {ok,N} when is_integer(N) ->
			   case application:get_env(kernel,
						    inet_dist_listen_max) of
			       {ok,M} when is_integer(M) ->
				   {N,M};
			       _ ->
				   {N,N}
			   end;
		       _ ->
			   {0,0}
		   end,
    %% 獲取綁定IP地址
    Options = case application:get_env(kernel, inet_dist_use_interface) of
		   {ok, Ip} ->
		       [{ip, Ip} | Options0];
		   _ ->
		       Options0
	       end,
    do_listen(First, Last, [{backlog,128}|Options]).

do_listen(First,Last,_) when First > Last ->
    {error,eaddrinuse};
do_listen(First,Last,Options) ->
    %% 嘗試監聽socket
    case inet_tcp:listen(First, Options) of
	{error, eaddrinuse} ->
	    do_listen(First+1,Last,Options);
	Other ->
	    Other
    end.

2015/9/29 標題“erlang epmd 自定義端口號”改成“erlang集羣IP及端口管理”
2015/6/25 補充節點連接監聽端口設定方法
參考:http://blog.csdn.net/mycwq/article/details/46630743

發佈了159 篇原創文章 · 獲贊 81 · 訪問量 128萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章