生活随笔
收集整理的這篇文章主要介紹了
《Erlang/OTP并发编程实战》第八章 分布式 Erlang/OTP 简介
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在 Erlang 中沒有共享,只有消息傳遞,因此分布式還是單機(jī)本質(zhì)上沒有什么區(qū)別。Erlang 集群是一個(gè)全聯(lián)通網(wǎng)絡(luò)。節(jié)點(diǎn)啟動(dòng): erl -name xx
適用于配有 DNS 的普通網(wǎng)絡(luò)環(huán)境,需要給出節(jié)點(diǎn)的完全限定域名erl -sname xx
適用于完全限定域名不可用的情況采用短節(jié)點(diǎn)名和長(zhǎng)節(jié)點(diǎn)名的節(jié)點(diǎn)所處的通信模式是不同的,它們之間無(wú)法形成集群。隱形節(jié)點(diǎn):
借助一些特殊的節(jié)點(diǎn),我們可以將多個(gè)集群合并成更大的、非全聯(lián)通的集群。
這類節(jié)點(diǎn)經(jīng)過特殊配置,不會(huì)對(duì)外傳播其他節(jié)點(diǎn)的信息,它們甚至可以對(duì)其他節(jié)點(diǎn)隱身,以便對(duì)集群進(jìn)行非侵入式監(jiān)控。建立連接: net_adm:ping('haha@haha.com'). ?
EPMD(Erlang 端口映射守護(hù)進(jìn)程): 啟動(dòng)每一個(gè)節(jié)點(diǎn),EPMD 都會(huì)檢查本地機(jī)器上是否運(yùn)行著 EPMD,如果沒有,節(jié)點(diǎn)就會(huì)自動(dòng)啟動(dòng) EPMD;EPMD 會(huì)追蹤在本地機(jī)器上運(yùn)行的每個(gè)節(jié)點(diǎn),并記錄分配給它們的端口號(hào);當(dāng)一臺(tái)機(jī)器上的 Erlang 節(jié)點(diǎn)試圖與遠(yuǎn)程節(jié)點(diǎn)通信時(shí), 本地的 EPMD 就會(huì)聯(lián)絡(luò)遠(yuǎn)程機(jī)器上的 EPMD(默認(rèn)使用TCP/IP,端口號(hào)4369),詢問在遠(yuǎn)程機(jī)器上有沒有相應(yīng)名字的節(jié)點(diǎn)。如果有,遠(yuǎn)程 EPMD 就會(huì)回復(fù)一個(gè)端口號(hào),通過該端口便可直接與遠(yuǎn)程節(jié)點(diǎn)通信;EPMD 不會(huì)主動(dòng)搜尋其他 EPMD,只有在某個(gè)節(jié)點(diǎn)主動(dòng)搜尋其他節(jié)點(diǎn)時(shí)才能建立。通信安全:
Erlang 默認(rèn)的分布式模型基于這樣一個(gè)假設(shè),集群中的所有節(jié)點(diǎn)都運(yùn)行在一個(gè)受信網(wǎng)絡(luò)內(nèi)。
如果這個(gè)假設(shè)不成立,或者其中的某些機(jī)器需要與外界通信,那么就應(yīng)該直接在TCP(或 UDP、SCTP 等)之上配合恰當(dāng)?shù)膽?yīng)用層協(xié)議來(lái)實(shí)現(xiàn)非受信網(wǎng)絡(luò)上的通信。此外還可以利用 SSL、SSH、IPsec 等技術(shù)建立加密隧道,甚至直接將 Erlang 的分布式通信層架設(shè)在 SSL 等傳輸協(xié)議之上。? auth:get_cookie(). % 獲取當(dāng)前節(jié)點(diǎn)的 cookie
set_cookie(Node, Cookie). % 設(shè)置 cookie ?
在 Erlang 中,shell 是采用進(jìn)程來(lái)容錯(cuò)的。shell 進(jìn)程崩潰后,信箱中的內(nèi)容會(huì)丟失,但變量綁定關(guān)系仍然會(huì)保留。遠(yuǎn)程使用 shell: 節(jié)點(diǎn)之間事先無(wú)須建立連接Ctrl-G 命令下:r 'a@haha.com'如果節(jié)點(diǎn)名中含有句點(diǎn),要加上單引號(hào)命令不會(huì)立即見效退出遠(yuǎn)程 shell 時(shí)注意:!!!不要用 q(). q() 是關(guān)閉執(zhí)行該命令的節(jié)點(diǎn),也就是遠(yuǎn)程節(jié)點(diǎn)。
要想安全退出,要使用 Ctrl-G 或 Ctrl-C資源探測(cè)應(yīng)用: 資源探測(cè):建立資源提供方和資源使用方之間的關(guān)系代碼實(shí)現(xiàn): -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 ofnoreply ->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 ->Accendend,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. ?
總結(jié)
以上是生活随笔為你收集整理的《Erlang/OTP并发编程实战》第八章 分布式 Erlang/OTP 简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。