- 在 Erlang 中没有共享,只有消息传递,因此分布式还是单机本质上没有什么区别。
- Erlang 集群是一个全联通网络。
- 节点启动:
- erl -name xx
适用于配有 DNS 的普通网络环境,需要给出节点的完全限定域名 - erl -sname xx
适用于完全限定域名不可用的情况
- erl -name xx
- 采用短节点名和长节点名的节点所处的通信模式是不同的,它们之间无法形成集群。
- 隐形节点:
借助一些特殊的节点,我们可以将多个集群合并成更大的、非全联通的集群。
这类节点经过特殊配置,不会对外传播其他节点的信息,它们甚至可以对其他节点隐身,以便对集群进行非侵入式监控。 - 建立连接:
net_adm:ping('[email protected]').
- EPMD(Erlang 端口映射守护进程):
- 启动每一个节点,EPMD 都会检查本地机器上是否运行着 EPMD,如果没有,节点就会自动启动 EPMD;
- EPMD 会追踪在本地机器上运行的每个节点,并记录分配给它们的端口号;
- 当一台机器上的 Erlang 节点试图与远程节点通信时, 本地的 EPMD 就会联络远程机器上的 EPMD(默认使用TCP/IP,端口号4369),询问在远程机器上有没有相应名字的节点。如果有,远程 EPMD 就会回复一个端口号,通过该端口便可直接与远程节点通信;
- EPMD 不会主动搜寻其他 EPMD,只有在某个节点主动搜寻其他节点时才能建立。
- 通信安全:
Erlang 默认的分布式模型基于这样一个假设,集群中的所有节点都运行在一个受信网络内。
如果这个假设不成立,或者其中的某些机器需要与外界通信,那么就应该直接在TCP(或 UDP、SCTP 等)之上配合恰当的应用层协议来实现非受信网络上的通信。此外还可以利用 SSL、SSH、IPsec 等技术建立加密隧道,甚至直接将 Erlang 的分布式通信层架设在 SSL 等传输协议之上。 -
auth:get_cookie(). % 获取当前节点的 cookie set_cookie(Node, Cookie). % 设置 cookie
- 在 Erlang 中,shell 是采用进程来容错的。shell 进程崩溃后,信箱中的内容会丢失,但变量绑定关系仍然会保留。
- 远程使用 shell:
- 节点之间事先无须建立连接
- Ctrl-G 命令下:r '[email protected]'
- 如果节点名中含有句点,要加上单引号
- 命令不会立即见效
- 退出远程 shell 时注意:!!!不要用 q(). q() 是关闭执行该命令的节点,也就是远程节点。
要想安全退出,要使用 Ctrl-G 或 Ctrl-C
- 资源探测应用:
- 资源探测:建立资源提供方和资源使用方之间的关系
- 代码实现:
-module(resource_discovery). -behavior(gen_server). %% API -export([start_link/0, add_target_resource_type/1, add_local_resource/2, fetch_resources/1, trade_resources/0]). -export([ init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 ]). -define(SERVER, ?MODULE). -record(state, {target_resource_types, local_resource_tuples, found_resource_tuples}). start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). init([]) -> {ok, #state{target_resource_types = [], local_resource_tuples = dict:new(), found_resource_tuples = dict:new()}}. add_target_resource_type(Type) -> gen_server:cast(?SERVER, {add_target_resource_type, Type}). add_local_resource(Type, Instance) -> gen_server:cast(?SERVER, {add_local_resource, {Type, Instance}}). fetch_resources(Type) -> gen_server:call(?SERVER, {fetch_resources, Type}). trade_resources() -> gen_server:cast(?SERVER, trade_resources). handle_cast({add_target_resource_type, Type}, State) -> TargetTypes = State#state.target_resource_types, NewTargetTypes = [Type | lists:delete(Type, TargetTypes)], {noreply, State#state{target_resource_types = NewTargetTypes}}; handle_cast({add_local_resource, {Type, Instance}}, State) -> ResourceTuples = State#state.local_resource_tuples, NewResourceTuples = add_resource(Type, Instance, ResourceTuples), {noreply, State#state{local_resource_tuples = NewResourceTuples}}; handle_cast(trade_resources, State) -> ResourceTuples = State#state.local_resource_tuples, AllNodes = [node() | nodes()], lists:foreach( fun(Node) -> gen_server:cast({?SERVER, Node}, {trade_resources, {node(), ResourceTuples}}) end, AllNodes), {noreply, State}; handle_cast({trade_resources, {ReplyTo, Remotes}}, State) -> #state{local_resource_tuples = Locals, target_resource_types = TargetTypes, found_resource_tuples = OldFound} = State, FilteredRemotes = resource_for_types(TargetTypes, Remotes), NewFound = add_resources(FilteredRemotes, OldFound), case ReplyTo of noreply -> ok; _ -> gen_server:cast({?SERVER, ReplyTo}, {trade_resources, {noreply, Locals}}) end, {noreply, State#state{found_resource_tuples = NewFound}}. handle_call({fetch_resources, Type}, _From, State) -> {reply, dict:find(Type, State#state.local_resource_tuples), State}. handle_info(_, State) -> {stop, normal, State}. terminate(_Reason, _State) -> sc_store:delete(self()), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. add_resources([{Type, Resource} | T ], ResourceTuples) -> add_resources(T, add_resource(Type, Resource, ResourceTuples)); add_resources([], ResourceTuples) -> ResourceTuples. resource_for_types(Types, ResourceTuples) -> Fun = fun(Type, Acc) -> case dict:find(Type, ResourceTuples) of {ok, List} -> [{Type, Instance} || Instance <- List] ++ Acc; error -> Acc end end, lists:foldl(Fun, [], Types). add_resource(Type, Resource, ResourceTuples) -> case dict:find(Type, ResourceTuples) of {ok, ResourceList} -> NewList = [Resource | lists:delete(Resource, ResourceList)], dict:store(Type, NewList, ResourceTuples); error -> dict:store(Type, [Resource], ResourceTuples) end.
《Erlang/OTP并发编程实战》第八章 分布式 Erlang/OTP 简介
猜你喜欢
转载自blog.csdn.net/sanmao123456_/article/details/103481125
今日推荐
周排行