Erlang 基础学习 8 Distributed programming

本文介绍了Erlang分布式编程的基础概念和技术实现,包括为何需要分布式程序、两种主要的实现方式(分布式Erlang和基于Socket的分布式)、以及通过示例程序讲解如何在不同环境下部署和访问分布式Erlang应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Distributed Programming

为啥需要分布式的程序?

• 性能,可以把程序的不同部分跑在不同的机器上
• 可靠性,我们可以构建一种容错机制,如果一台机器挂了,可以把他的工作交给其他机器去完成
• 伸缩性,如果向上扩展的话,再好的机器也有个头,但是我们可以向外扩展,添加新的机器进来提高计算能力

这里会介绍两种分布式的实现方式
• 1. 分布式的erlang,提供一种机制让erlang程序运行在一组服务器上,以前介绍的所有的消息机制,spawn等都可以一致的工作
• 分布式的erlang程序应该工作在一个可以信任的环境里,因为任何程序都可以操作任何节点上的东西,一般分布式的erlang都是运行在防火墙后的局域网内
• 2. 基于socket的分布式,使用TCP/IP socket,可以开发更安全的分布式系统,可以工作在不安全的环境下,不过这种模式没有分布式erlang那么强大的功能,但是更安全。


• 实际上,erlang程序工作的基本单元是process,分布式的编程实际上就是在合适的节点上启动合适的进程
• 一般开发分布式的erlang程序的流程
• 首先,开发一个单机程序
• 然后,在同一台机器上测试两个节点的情况
• 最后,在多台物理机器上测试

示例程序:
-module(kvs).
-export([start/0, store/2, lookup/1]).
start() -> register(kvs, spawn(fun() -> loop() end)).
store(Key, Value) -> rpc({store, Key, Value}).
lookup(Key) -> rpc({lookup, Key}).
rpc(Q) ->
    kvs ! {self(), Q},
    receive
        {kvs, Reply} ->
            Reply
    end.
loop() ->
    receive
        {From, {store, Key, Value}} ->
            put(Key, {ok, Value}),
            From ! {kvs, true},
            loop();
        {From, {lookup, Key}} ->
            From ! {kvs, get(Key)},
            loop()
    end.

• 我们将用这个示例程序来学习分布式的访问
• 1. 在本地访问,很简单
• 2. 在同一台机器的两个节点上访问
• 起两个shell,分别用-sname来给两个节点起名字
• 用rpc:call(Node,Mod,Fun,Params).来访问远程的程序
• 3. 在局域网内的两台机器上分别起节点
• 用-name Name@Domain -setcookie Cookie来启动两个节点,注意Cookie要一致
• 另外就是Domain要能够互相访问到,可以用hosts来绑定
• 访问方法相同
• 4. 在互联网上,两台服务器分别起节点
• 注意在防火墙上要允许4369端口的TCP/UDP访问
• 另外需要指定一个或一系列端口来进行访问,
• erl -name ... -setcookie ... -kernel inet_dist_listen_min Min inet_dist_listen_max Max

• 另外,在多台机器上的程序代码和erlang版本要一致,要保证代码一致,可以:
• 1. 拷贝代码,每个节点分别装载
• 2. 使用共享的文件系统,NFS
• 3. 使用code server,参考erl_prim_loader模块的说明(还没实验过)
• 4. 使用nl(Mod)来广播,可以将已经连接的多个节点同步指定的module
• 只有在发生过远程请求之后,节点才算“已连接”,可以使用net_adm:ping(Node)来连接

分布式erlang的基本要素
• 以节点为基本单元
• 节点要能互相连接需要有同样的cookie,cookie相当于是一个身份验证的机制
• 有几种方式来保证有同样的cookie
• 1. 在启动时指定 erl -setcookie Cookie
• 2. 在$HOME/.erlang.cookie中指定,文件需要400权限
• 3. 在程序里用erlang.set_cookie(Cookie)指定, erlang:set_cookie(node(), C)指定某个node的cookie
• 一些基本的BIF:
• @spec spawn(Node, Fun) -> Pid
• @spec spawn(Node, Mod, Func, ArgList) -> Pid
• @spec spawn_link(Node, Fun) -> Pid
• @spec spawn_link(Node, Mod, Func, ArgList) -> Pid
• @spec disconnect_node(Node) -> bool() | ignored  与Node断开连接
• @spec monitor_node(Node, Flag) -> true  监视Node,如果Flag为true就打开监视,否则关闭监视
• 如果被监视的Node加入或者退出的时候,监视者会收到{nodeup, Node} 或{nodedown,Node}的消息
• @spec node() -> Node 返回本地node的名字,如果没有分布式,返回nonode@nohost
• @spec node(Arg) -> Node
• @spec nodes() -> [Node] 返回已连接的节点名列表
• @spec is_alive() -> bool() 本地节点是否在一个分布式的erlang集群中
• 另外,发送消息{RegName, Node} ! Msg

远程spawn例子
-module(dist_demo).
-export([rpc/4, start/1]).
start(Node) ->
    spawn(Node, fun() -> loop() end).
rpc(Pid, M, F, A) ->
    Pid ! {rpc, self(), M, F, A},
    receive
        {Pid, Response} ->
            Response
    end.
loop() ->
    receive
        {rpc, Pid, M, F, A} ->
            Pid ! {self(), (catch apply(M, F, A))},
            loop()
    end.

rpc:call(Node, Mod, Function, Args) -> Result | {badrpc, Reason}

socket based distribute.
lib_chan ,可以将某个服务起个别名启动,监听某一端口,并且可以有密码保护,使用这个服务也一样提供密码。erl在服务端和客户端分别起一个进程来做翻译,将erlang的消息和tcp的包进行互相的翻译

-module(mod_name_server).
-export([start_me_up/3]).
start_me_up(MM, _ArgsC, _ArgS) ->
    loop(MM).
loop(MM) ->
    receive
        {chan, MM, {store, K, V}} ->
            kvs:store(K, V),
            loop(MM);
        {chan, MM, {lookup, K}} ->
            MM ! {send, kvs:lookup(K)},
            loop(MM);
        {chan_closed, MM} ->
            true
    end.




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值