转载请注明,来自:http://blog.csdn.net/skyman_2001
Erlang的节点之间的连接默认是transitive,即当节点A连接了节点B,节点B连接了节点C,那么节点A也与节点C互相连接,这样就组成了全连通网络。但有时我们希望连接一个节点而不去连接其他节点(比如某个节点只是用来查看集群的一些信息),这时可以通过指定该节点为hidden节点来实现(在节点启动时指定-hidden参数),hidden节点不加入集群全连通网络。hidden节点还能降低TCP/IP的连接数:因为如果一个集群里的节点数是N,则全连通的话,需要的TCP/IP连接数则为:N * (N - 1) / 2,所以将没必要全连通的节点设为hidden节点,会将该节点从全连通网络中移除,从而降低TCP/IP连接数。
注意nodes() 默认是不返回hidden节点的,指定参数hidden或connected(即nodes(hidden)或nodes(connected))可返回hidden节点的信息。
下面摘录官方文档里关于hidden节点的说明(就不翻译成中文了^ ^):
In a distributed Erlang system, it is sometimes useful to connect to a node without also connecting to all other nodes. An example could be some kind of O&M functionality used to inspect the status of a system without disturbing it. For this purpose, a hidden node may be used.
A hidden node is a node started with the command line flag -hidden. Connections between hidden nodes and other nodes are not transitive, they must be set up explicitly. Also, hidden nodes does not show up in the list of nodes returned by nodes(). Instead, nodes(hidden) or nodes(connected) must be used. This means, for example, that the hidden node will not be added to the set of nodes that global is keeping track of.
更深入的了解,可以阅读余锋老大的文章:http://www.iteye.com/topic/343088
但是hidden节点有个问题,就是不能自动同步它里面注册的全局进程名(使用global:sync/0也不行),我目前使用的一个方法是通过rpc来获得它已注册的全局进程名和对应的pid,然后在本地节点再手动注册,下面是我封装的函数:
sync_registered_names(Node) ->
Registered_names = rpc:call(Node, global, registered_names, []),
F = fun(Name) ->
Pid = rpc:call(Node, global, whereis_name, [Name]),
global:register_name(Name, Pid)
end,
[F(Name) || Name <- Registered_names].
不知道有没有更好的方法?若有知道的童鞋可以告知一下,不胜感激!
下面说下hide和connect_all false的区别:
看文档:
If this flag is present, global will not maintain a fully connected network of distributed Erlang nodes, and then global name registration cannot be used.
1. 结果来看的话都是节点不全联通。
2. nodes() 是默认不返回hidden节点的 但是返回正常节点尽管connect_all false
3. rpc、monitor什么的都依赖nodes(),比如net_kernel:monitor_nodes(),默认是不包括hidden节点的,要包括的话,Options选项中的node_type要设为hidden或all:
Also, when OptionList == [] only visible nodes, that is, nodes that appear in the result of nodes/0, are monitored.
Option can be any of the following:
-
{node_type, NodeType}
-
Currently valid values for NodeType are:
-
visible
- Subscribe to node status change messages for visible nodes only. The tuple {node_type, visible} is included in InfoList. hidden
- Subscribe to node status change messages for hidden nodes only. The tuple {node_type, hidden} is included in InfoList. all
- Subscribe to node status change messages for both visible and hidden nodes. The tuple {node_type, visible | hidden} is included in InfoList.
4. 系统统计也会不同
5. hidden是在erts实现的 connect_all是在global模块实现的
在connect_all false情况下,调用global:sync会一直卡住,看它的实现代码:
-spec sync() -> 'ok' | {'error', Reason :: term()}.
sync() ->
case check_sync_nodes() of
{error, _} = Error ->
Error;
SyncNodes ->
gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
end.
这里的call的timeout是infinity,上面的文档说了connect_all false时global name registration不可用,所以就一直等待了。
最后说一个,不同cookie的节点怎么连通呢?方法是连接前erlang:set_cookie(Node2, DiffCookie),参考:http://www.iteye.com/topic/356611
The default when a connection is established between two nodes, is to immediately connect all other visible nodes as well. This way, there is always a fully connected network. If there are nodes with different cookies, this method might be inappropriate and the command line flag -connect_all false must be set