區服節點互連
(金慶的專欄)
【上海龍圖招聘】
所有Erlang服務器節點加入同一集群,使用相同的cookie。
使用BIF erlang:set_cookie(node(), C)把本地節點的cookie設置為原子C。
1個或多個節點配置為主節點(主服務器)。
主節點不必全部啟動,但要求至少啟動1個。
主節點配置可熱更新即時生效。
主節點啟動后,主動連接所有未連接的主節點,每隔5s嘗試連接。
其他節點,如新開區服,僅需連接主節點。
所有主節點和其他節點最終全互連。
僅需配置主服務器內網地址,利用net_adm:world_list([Host])連接所有節點。
客戶端僅需配置數個主服務器的地址,連上某個主服后即可查詢所有服務器的地址與負載。
客戶端一般會記錄后最連接的服務器,用于角色重登,同樣也可查詢服務器列表。
ping_main_hosts() ->
MainHosts = config_main_hosts:get(),
Nodes = net_adm:world_list(MainHosts),
lager:debug("Ping main hosts: ~p. Result nodes: ~p", [MainHosts, Nodes]),
ok.
18:34:45.023 [debug] Ping main hosts: ['127.0.0.1']. Result nodes: []
18:34:50.029 [debug] Ping main hosts: ['127.0.0.1']. Result nodes: []
Reloading config_main_hosts ... ok.
18:34:55.272 [debug] Ping main hosts: ['192.168.8.9','127.0.0.1']. Result nodes: ['s3@192.168.8.9']
18:35:00.057 [debug] Ping main hosts: ['192.168.8.9','127.0.0.1']. Result nodes: ['s3@192.168.8.9']
cluster_svr 處理集群互連。
%%%-------------------------------------------------------------------
%%% @author jinqing
%%% @copyright (C) 2015, <COMPANY>
%%% @doc 集群互連服務器。
%%% 處理集群互連。廣播自身節點狀態,接收其他節點狀態。
%%% @end
%%% Created : 23. 四月 2015 12:12
%%%-------------------------------------------------------------------
-module(cluster_svr).
-author("jinqing").
-behaviour(gen_server).
...
-type state() :: #{nodes => [node()]}.
-type server_info() :: #{host_cfg => config_gateway:host_cfg(),
current_load => integer()}.
-export_type([server_info/0]).
...
init([]) ->
init_ets(),
init_timer(),
{ok, #{}}.
...
handle_info(timer_ping, State) ->
NewState = timer_ping(State),
{noreply, NewState};
handle_info(timer_bcast_info, State) ->
timer_bcast_info(),
{noreply, State};
handle_info({server_info, ServerId, ServerInfo}, State)
when is_integer(ServerId), is_map(ServerInfo) ->
lager:debug("~p Server~p info: ~p", [self(), ServerId, ServerInfo]),
ets:insert(ets_server, {ServerId, ServerInfo}),
{noreply, State};
...
init_timer() ->
% 啟動時短時間內Ping多次,接著每隔10s定時Ping.
{ok, _} = timer:send_after(200, self(), timer_ping),
{ok, _} = timer:send_after(1000, self(), timer_ping),
{ok, _} = timer:send_interval(10000, self(), timer_ping),
{ok, _} = timer:send_after(2000, self(), timer_bcast_info),
{ok, _} = timer:send_after(5000, self(), timer_bcast_info),
{ok, _} = timer:send_interval(31000, self(), timer_bcast_info),
ok.
init_ets() ->
ets:new(ets_server, [named_table]), % 區服列表
ok.
-spec timer_ping(State :: state()) -> state().
timer_ping(State) ->
% lager:debug("timer_ping"),
spawn(cluster_ping, ping_main_hosts, []),
PrevNodes = maps:get(nodes, State, []),
Nodes = nodes(),
case (Nodes =:= PrevNodes) of
true -> State;
_ ->
% 如果有節點更新,就打印節點列表。
AllNodes = [node() | Nodes],
lager:info("All nodes: ~p", [AllNodes]),
State#{nodes => Nodes}
end.
timer_bcast_info() ->
% lager:debug("timer_bcast_info"),
ServerId = six_util:get_server_id(),
ServerInfo = cluster_server_info:get(ServerId),
rpc:abcast(nodes(), ?MODULE, {server_info, ServerId, ServerInfo}),
ok.
【上海龍圖招聘】
(金慶的專欄)
【上海龍圖招聘】
所有Erlang服務器節點加入同一集群,使用相同的cookie。
使用BIF erlang:set_cookie(node(), C)把本地節點的cookie設置為原子C。
1個或多個節點配置為主節點(主服務器)。
主節點不必全部啟動,但要求至少啟動1個。
主節點配置可熱更新即時生效。
主節點啟動后,主動連接所有未連接的主節點,每隔5s嘗試連接。
其他節點,如新開區服,僅需連接主節點。
所有主節點和其他節點最終全互連。
僅需配置主服務器內網地址,利用net_adm:world_list([Host])連接所有節點。
客戶端僅需配置數個主服務器的地址,連上某個主服后即可查詢所有服務器的地址與負載。
客戶端一般會記錄后最連接的服務器,用于角色重登,同樣也可查詢服務器列表。
ping_main_hosts() ->
MainHosts = config_main_hosts:get(),
Nodes = net_adm:world_list(MainHosts),
lager:debug("Ping main hosts: ~p. Result nodes: ~p", [MainHosts, Nodes]),
ok.
18:34:45.023 [debug] Ping main hosts: ['127.0.0.1']. Result nodes: []
18:34:50.029 [debug] Ping main hosts: ['127.0.0.1']. Result nodes: []
Reloading config_main_hosts ... ok.
18:34:55.272 [debug] Ping main hosts: ['192.168.8.9','127.0.0.1']. Result nodes: ['s3@192.168.8.9']
18:35:00.057 [debug] Ping main hosts: ['192.168.8.9','127.0.0.1']. Result nodes: ['s3@192.168.8.9']
cluster_svr 處理集群互連。
%%%-------------------------------------------------------------------
%%% @author jinqing
%%% @copyright (C) 2015, <COMPANY>
%%% @doc 集群互連服務器。
%%% 處理集群互連。廣播自身節點狀態,接收其他節點狀態。
%%% @end
%%% Created : 23. 四月 2015 12:12
%%%-------------------------------------------------------------------
-module(cluster_svr).
-author("jinqing").
-behaviour(gen_server).
...
-type state() :: #{nodes => [node()]}.
-type server_info() :: #{host_cfg => config_gateway:host_cfg(),
current_load => integer()}.
-export_type([server_info/0]).
...
init([]) ->
init_ets(),
init_timer(),
{ok, #{}}.
...
handle_info(timer_ping, State) ->
NewState = timer_ping(State),
{noreply, NewState};
handle_info(timer_bcast_info, State) ->
timer_bcast_info(),
{noreply, State};
handle_info({server_info, ServerId, ServerInfo}, State)
when is_integer(ServerId), is_map(ServerInfo) ->
lager:debug("~p Server~p info: ~p", [self(), ServerId, ServerInfo]),
ets:insert(ets_server, {ServerId, ServerInfo}),
{noreply, State};
...
init_timer() ->
% 啟動時短時間內Ping多次,接著每隔10s定時Ping.
{ok, _} = timer:send_after(200, self(), timer_ping),
{ok, _} = timer:send_after(1000, self(), timer_ping),
{ok, _} = timer:send_interval(10000, self(), timer_ping),
{ok, _} = timer:send_after(2000, self(), timer_bcast_info),
{ok, _} = timer:send_after(5000, self(), timer_bcast_info),
{ok, _} = timer:send_interval(31000, self(), timer_bcast_info),
ok.
init_ets() ->
ets:new(ets_server, [named_table]), % 區服列表
ok.
-spec timer_ping(State :: state()) -> state().
timer_ping(State) ->
% lager:debug("timer_ping"),
spawn(cluster_ping, ping_main_hosts, []),
PrevNodes = maps:get(nodes, State, []),
Nodes = nodes(),
case (Nodes =:= PrevNodes) of
true -> State;
_ ->
% 如果有節點更新,就打印節點列表。
AllNodes = [node() | Nodes],
lager:info("All nodes: ~p", [AllNodes]),
State#{nodes => Nodes}
end.
timer_bcast_info() ->
% lager:debug("timer_bcast_info"),
ServerId = six_util:get_server_id(),
ServerInfo = cluster_server_info:get(ServerId),
rpc:abcast(nodes(), ?MODULE, {server_info, ServerId, ServerInfo}),
ok.
【上海龍圖招聘】