查看源代码 net_kernel (kernel v10.2)
Erlang 网络内核。
网络内核是一个系统进程,注册为 net_kernel
,它必须运行才能使分布式 Erlang 工作。此进程的目的是实现 BIFs spawn/4
和 spawn_link/4
的一部分,并提供对网络的监控。
Erlang 节点使用命令行标志 -name
或 -sname
启动
$ erl -sname foobar
也可以直接从正常的 Erlang shell 提示符调用 net_kernel:start(foobar, #{})
1> net_kernel:start(foobar, #{name_domain => shortnames}).
{ok,<0.64.0>}
(foobar@gringotts)2>
如果节点使用命令行标志 -sname
启动,则节点名称为 foobar@Host
,其中 Host
是主机的简称(不是完全限定域名)。如果使用标志 -name
启动,则节点名称为 foobar@Host
,其中 Host
是完全限定域名。有关详细信息,请参阅 erl
。
通常,当引用另一个节点时,会自动建立连接。可以通过将内核配置参数 dist_auto_connect
设置为 never
来禁用此功能,请参阅 kernel(6)
。在这种情况下,必须通过调用 connect_node/1
来显式建立连接。
哪些节点允许相互通信由 magic cookie 系统处理,请参阅 Erlang 参考手册中的 分布式 Erlang 部分。
警告
启动分布式节点而不指定
-proto_dist inet_tls
会使节点容易受到攻击,这些攻击可能会使攻击者完全访问节点并在扩展中访问集群。当使用不安全的分布式节点时,请确保配置网络以阻止潜在的攻击者。有关如何设置安全分布式节点的详细信息,请参阅 使用 SSL 进行 Erlang 分布用户指南。
概要
函数
允许访问指定的节点集。
建立与 Node
的连接。
返回当前使用的网络滴答时间(以秒为单位)。
获取本地节点的分布的当前状态。
获取连接到 Node
的分布套接字的一个或多个选项。
调用进程订阅或取消订阅节点状态更改消息。当新节点连接时,会向所有订阅进程传递 nodeup
消息,当节点断开连接时,会传递 nodedown
消息。
将 net_ticktime
(请参阅 kernel(6)
)设置为 NetTicktime
秒。TransitionPeriod
默认为 60
。
设置分布套接字的一个或多个选项。参数 Node
可以是一个节点名称,也可以是原子 new
,以影响所有未来连接节点的分布套接字。
通过启动 net_kernel
和其他必要的进程,将非分布式节点转换为分布式节点。
通过启动 net_kernel
和其他必要的进程,将非分布式节点转换为分布式节点。
将分布式节点转换为非分布式节点。
类型
函数
-spec allow(Nodes) -> ok | error when Nodes :: [node()].
允许访问指定的节点集。
在第一次调用 allow/1
之前,任何具有正确 cookie 的节点都可以连接。当调用 allow/1
时,会建立允许节点的列表。任何来自(或到)该列表中未包含的节点的访问尝试都将被拒绝。
后续对 allow/1
的调用会将指定的节点添加到允许的节点列表中。无法从列表中删除节点。
如果 Nodes
中的任何元素不是原子,则返回 error
。
建立与 Node
的连接。
如果建立了连接或已建立连接,或者如果 Node
是本地节点本身,则返回 true
。如果连接尝试失败,则返回 false
,如果本地节点未处于活动状态,则返回 ignored
。
-spec get_net_ticktime() -> Res when Res :: NetTicktime | {ongoing_change_to, NetTicktime} | ignored, NetTicktime :: pos_integer().
返回当前使用的网络滴答时间(以秒为单位)。
有关详细信息,请参阅 net_ticktime
Kernel
参数。
定义的返回值 (Res
)
NetTicktime
-net_ticktime
为NetTicktime
秒。{ongoing_change_to, NetTicktime}
-net_kernel
当前正在将net_ticktime
更改为NetTicktime
秒。ignored
- 本地节点未处于活动状态。
-spec get_state() -> #{started => no | static | dynamic, name => atom(), name_type => static | dynamic, name_domain => shortnames | longnames}.
获取本地节点的分布的当前状态。
返回一个包含(至少)以下键值对的映射
started => Started
-Started
的有效值no
- 分布未启动。在这种状态下,映射中不存在以下其他任何键。dynamic
- 分布是使用net_kernel:start/1
启动的,可以使用net_kernel:stop/0
停止。
name => Name
- 节点的名称。与erlang:node/0
返回的值相同,除非当name_type
为dynamic
时,在这种情况下,Name
可能为undefined
(而不是nonode@nohost
)。name_type => NameType
-NameType
的有效值static
- 节点具有由节点本身设置的静态节点名称。dynamic
- 分布以 动态节点名称模式启动,并将从它连接的第一个节点分配其节点名称。如果键name
的值为undefined
,则尚未发生这种情况。
name_domain => NameDomain
-NameDomain
的有效值shortnames
- 分布启动时使用带有简短主机部分(非完全限定)的节点名称。longnames
- 分布启动时使用带有长完全限定主机部分的节点名称。
-spec getopts(Node, Options) -> {ok, OptionValues} | {error, Reason} | ignored when Node :: node(), Options :: [inet:socket_getopt()], OptionValues :: [inet:socket_setopt()], Reason :: inet:posix() | noconnection.
获取连接到 Node
的分布套接字的一个或多个选项。
如果 Node
是已连接的节点,则返回值与 inet:getopts(Sock, Options)
的返回值相同,其中 Sock
是 Node
的分布套接字。
如果本地节点未处于活动状态,则返回 ignored
,如果 Node
未连接,则返回 {error, noconnection}
。
-spec monitor_nodes(Flag, Options) -> ok | Error when Flag :: boolean(), Options :: OptionsList | OptionsMap, OptionsList :: [ListOption], ListOption :: connection_id | {node_type, NodeType} | nodedown_reason, OptionsMap :: #{connection_id => boolean(), node_type => NodeType, nodedown_reason => boolean()}, NodeType :: visible | hidden | all, Error :: error | {error, term()}.
调用进程订阅或取消订阅节点状态更改消息。当新节点连接时,会向所有订阅进程传递 nodeup
消息,当节点断开连接时,会传递 nodedown
消息。
如果 Flag
为 true
,则开始新的订阅。如果 Flag
为 false
,则停止所有先前使用相同 Options
开始的订阅。如果两个选项列表包含相同的选项集,则认为它们相同。
nodeup
/nodedown
消息的传递保证
nodeup
消息在通过新建立的连接从远程节点传递任何信号之前传递。nodedown
消息在来自远程节点的所有信号通过连接传递后传递。nodeup
消息在相应节点出现在erlang:nodes()
的结果中后传递。nodedown
消息在相应节点从erlang:nodes()
的结果中消失后传递。- 从 OTP 23.0 开始,将关闭连接的
nodedown
消息将在由于与同一节点的新连接而产生的nodeup
消息之前传递。在 OTP 23.0 之前,不保证这种情况。
节点状态更改消息的格式取决于 Options
。如果 Options
是空列表,或者如果调用了 net_kernel:monitor_nodes/1
,则格式如下
{nodeup, Node} | {nodedown, Node}
Node = node()
当 Options
为空映射或空列表时,调用方将仅订阅可见节点的状态更改消息。也就是说,仅订阅出现在 erlang:nodes/0
的结果中的节点。
如果 Options
不等于空列表,则状态更改消息的格式如下
{nodeup, Node, Info} | {nodedown, Node, Info}
Node = node()
Info = #{Tag => Val} | [{Tag, Val}]
Info
是映射或 2 元组列表。其内容取决于 Options
。如果 Options
是映射,则 Info
也将是映射。如果 Options
是列表,则 Info
也将是列表。
当 Options
是映射时,目前允许以下关联
connection_id => boolean()
- 如果关联的值等于true
,则Info
映射中将包含connection_id => ConnectionId
关联,其中ConnectionId
是正在启动或关闭的连接的连接标识符。有关此连接标识符的更多信息,请参阅 erlang:nodes/2 的文档。node_type => NodeType
-NodeType
的有效值visible
- 仅订阅可见节点的节点状态更改消息。Info
映射中将包含关联node_type => visible
。hidden
- 仅订阅隐藏节点的状态更改消息。关联node_type => hidden
将包含在Info
映射中。all
- 订阅可见和隐藏节点的状态更改消息。关联node_type => visible | hidden
将包含在Info
映射中。
如果
Options
映射中未包含node_type => NodeType
关联,则调用者将仅订阅可见节点的状态更改消息,但Info
映射中将不包含node_type => visible
关联。nodedown_reason => boolean()
- 如果该关联的值等于true
,则nodedown
消息的Info
映射中将包含nodedown_reason => Reason
关联。Reason
可以是任何项,具体取决于所使用的分发模块或进程,但对于标准的 TCP 分发模块,它是以下之一connection_setup_failed
- 连接设置失败(在发送nodeup
消息后)。no_network
- 没有可用的网络。net_kernel_terminated
-net_kernel
进程终止。shutdown
- 未指定的连接关闭。connection_closed
- 连接已关闭。disconnect
- 连接已断开(从当前节点强制断开)。net_tick_timeout
- 网络心跳超时。send_net_tick_failed
- 无法通过连接发送网络心跳。get_status_failed
- 从保存连接的Port
中检索状态信息失败。
当 Options
是一个列表时,目前 ListOption
可以是以下之一
connection_id
-Info
中将包含一个{connection_id, ConnectionId}
元组,其中ConnectionId
是正在建立或关闭的连接的连接标识符。有关此连接标识符的更多信息,请参阅 erlang:nodes/2 的文档。{node_type, NodeType}
-NodeType
的有效值visible
- 仅订阅可见节点的状态更改消息。元组{node_type, visible}
将包含在Info
列表中。hidden
- 仅订阅隐藏节点的状态更改消息。元组{node_type, hidden}
将包含在Info
列表中。all
- 订阅可见和隐藏节点的状态更改消息。元组{node_type, visible | hidden}
将包含在Info
列表中。
如果未提供任何
{node_type, NodeType}
选项。调用者将仅订阅可见节点的状态更改消息,但Info
列表中将不包含{node_type, visible}
元组。nodedown_reason
-nodedown
消息的Info
列表中将包含元组{nodedown_reason, Reason}
。有关可能的
Reason
值的信息,请参阅上面nodedown_reason => boolean()
关联的文档。
示例
(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
ok
(a@localhost)2> flush().
Shell got {nodeup,b@localhost,
#{connection_id => 3067552,node_type => visible}}
Shell got {nodeup,c@localhost,
#{connection_id => 13892107,node_type => hidden}}
Shell got {nodedown,b@localhost,
#{connection_id => 3067552,node_type => visible,
nodedown_reason => connection_closed}}
Shell got {nodedown,c@localhost,
#{connection_id => 13892107,node_type => hidden,
nodedown_reason => net_tick_timeout}}
Shell got {nodeup,b@localhost,
#{connection_id => 3067553,node_type => visible}}
ok
(a@localhost)3>
-spec set_net_ticktime(NetTicktime) -> Res when NetTicktime :: pos_integer(), Res :: unchanged | change_initiated | {ongoing_change_to, NewNetTicktime}, NewNetTicktime :: pos_integer().
-spec set_net_ticktime(NetTicktime, TransitionPeriod) -> Res when NetTicktime :: pos_integer(), TransitionPeriod :: non_neg_integer(), Res :: unchanged | change_initiated | {ongoing_change_to, NewNetTicktime}, NewNetTicktime :: pos_integer().
将 net_ticktime
(请参阅 kernel(6)
)设置为 NetTicktime
秒。TransitionPeriod
默认为 60
。
一些定义
最小转换流量间隔 (
MTTI
) -minimum(NetTicktime, PreviousNetTicktime)*1000 div 4
毫秒。转换期 - 覆盖调用
set_net_ticktime/2
后TransitionPeriod
秒所需的最少连续MTTI
时间(即 ((TransitionPeriod*1000 - 1) div MTTI + 1)*MTTI
毫秒)。
如果 NetTicktime < PreviousNetTicktime
,则 net_ticktime
更改在转换期结束时完成;否则在开始时完成。在转换期间,net_kernel
确保所有连接上至少每 MTTI
毫秒有一次传出流量。
注意
必须在任何节点上的任何转换期结束之前,在网络中的所有节点上启动
net_ticktime
更改(使用相同的NetTicktime
);否则连接可能会被错误地断开。
返回以下之一
unchanged
-net_ticktime
已具有NetTicktime
的值,并且保持不变。change_initiated
-net_kernel
启动了将net_ticktime
更改为NetTicktime
秒的操作。{ongoing_change_to, NewNetTicktime}
- 该请求被忽略,因为net_kernel
正忙于将net_ticktime
更改为NewNetTicktime
秒。
-spec setopts(Node, Options) -> ok | {error, Reason} | ignored when Node :: node() | new, Options :: [inet:socket_setopt()], Reason :: inet:posix() | noconnection.
设置分布套接字的一个或多个选项。参数 Node
可以是一个节点名称,也可以是原子 new
,以影响所有未来连接节点的分布套接字。
返回值与 inet:setopts/2
的返回值相同,如果 Node
不是已连接的节点或 new
,则返回 {error, noconnection}
。
如果 Node
为 new
,则 Options
也将添加到内核配置参数 inet_dist_listen_options 和 inet_dist_connect_options 中。
如果本地节点未启动,则返回 ignored
。
-spec start(Options) -> {ok, pid()} | {error, Reason} when Options :: [Name | NameDomain | TickTime, ...], Name :: atom(), NameDomain :: shortnames | longnames, TickTime :: pos_integer(), Reason :: {already_started, pid()} | term().
通过启动 net_kernel
和其他必要的进程,将非分布式节点转换为分布式节点。
Options
列表只能是以下列表之一(顺序很重要)
[Name]
- 与net_kernel:start([Name, longnames, 15000])
相同。[Name, NameDomain]
- 与net_kernel:start([Name, NameDomain, 15000])
相同。[Name, NameDomain, TickTime]
- 与net_kernel:start(Name, #{name_domain => NameDomain, net_ticktime => ((TickTime*4-1) div 1000) + 1, net_tickintensity => 4})
相同。请注意,TickTime
与以毫秒表示的网络心跳时间不同。TickTime
是当网络心跳强度等于4
时,心跳之间的时间。
-spec start(Name, Options) -> {ok, pid()} | {error, Reason} when Options :: #{name_domain => NameDomain, net_ticktime => NetTickTime, net_tickintensity => NetTickIntensity, dist_listen => boolean(), hidden => boolean()}, Name :: atom(), NameDomain :: shortnames | longnames, NetTickTime :: pos_integer(), NetTickIntensity :: 4..1000, Reason :: {already_started, pid()} | term().
通过启动 net_kernel
和其他必要的进程,将非分布式节点转换为分布式节点。
如果 Name
设置为undefined
,则将启动分发以从它连接的第一个节点请求动态节点名称。请参阅 动态节点名称。将 Name
设置为 undefined
意味着选项 dist_listen => false
和 hidden => true
。
当前支持的选项
name_domain => NameDomain
- 确定节点名称的主机名部分。如果NameDomain
等于longnames
,则将使用完全限定的域名,这也是默认值。如果NameDomain
等于shortnames
,则仅使用主机的短名称。net_ticktime => NetTickTime
- 要使用的网络心跳时间(以秒为单位)。默认为net_ticktime
kernel(6)
参数的值。有关网络心跳时间的更多信息,请参阅kernel
参数。但是,请注意,如果kernel
参数的值无效,它将静默地替换为有效值,但如果将无效的NetTickTime
值作为选项值传递给此函数,则调用将失败。net_tickintensity => NetTickIntensity
- 要使用的网络心跳强度。默认为net_tickintensity
kernel(6)
参数的值。有关网络心跳强度的更多信息,请参阅kernel
参数。但是,请注意,如果kernel
参数的值无效,它将静默地替换为有效值,但如果将无效的NetTickIntensity
值作为选项值传递给此函数,则调用将失败。dist_listen => boolean()
- 启用或禁用侦听传入连接。默认为-dist_listen
erl
命令行参数的值。请注意,dist_listen => false
意味着hidden => true
。如果将
undefined
作为Name
传递,则dist_listen
选项将被dist_listen => false
覆盖。hidden => boolean()
- 启用或禁用隐藏节点。如果已传递-hidden
erl
命令行参数,则默认为true
;否则为false
。如果将
undefined
作为Name
传递,或者选项dist_listen
等于false
,则hidden
选项将被hidden => true
覆盖。
-spec stop() -> ok | {error, Reason} when Reason :: not_allowed | not_found.
将分布式节点转换为非分布式节点。
对于网络中的其他节点,这与节点关闭相同。仅当使用 start/2
启动网络内核时才有可能,否则返回 {error, not_allowed}
。如果本地节点未启动,则返回 {error, not_found}
。