锁定老帖子 主题:Erlang分布的核心技术浅析
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-06
最后修改:2009-01-12
erlang的分布系统做到了2点 1.节点的位置无关性。 2. 对用户分布式透明的。具体体现就是node是靠名字识别的, 进程也是靠pid来识别。 分布系统就要实现节点间通讯,erlang也不列外。 erlang的节点通讯介质是可以替换的 目前官方版本支持tcp, ssl通讯。 可以用 -proto_dist xxxx来选择通道。 目前支持inet_ssl inet_tcp 用户很容易模仿这这2个通讯协议,写个自己的传输通道,就是要求这个通道是可靠的,不能丢失信息。 这几个实现防火墙友好: {inet_dist_use_interface, ip_address()} If the host of an Erlang node has several network interfaces, this parameter specifies which one to listen on. See inet(3) for the type definition of ip_address(). {inet_dist_listen_min, First} See below. {inet_dist_listen_max, Last} Define the First..Last port range for the listener socket of a distributed Erlang node. erlang的内核里面和分布相关的erl模块主要有net_kernel inet_tcp_dist inet_ssl_dist inet_tcp dist_util erlang(trap send/link等语义)。 当用户运行erl -sname xxxxx启动erlang系统的时候 kernel模块就会启动net_kernel和epmd模块。 epmd的作用是提供一个node名称到监听地址端口的映射。epmd值守在知名端口4369上. net_kernel会启动proto_dist比如说inet_tcp_dist监听端口,同时把端口报到epmd. 这时候erts就准备好了节点通讯。 这时候另外一个节点要和我们通讯的时候,首先要连接,流程大概是这样的: 1. 根据节点名找到节点地址。 2. 查询节点的4369端口,也就是epmd,向它要节点对应的inet_tcp_dist监听的端口。 3. 发起连接, 握手,cookie认证,如果未授权就失败。 4. 记录节点名称和响应的信息。 所以节点要正常通讯要考虑到firewall和nat的影响,以及cookie正常。 具体的可以看另外一篇文章:http://mryufeng.iteye.com/blog/120666 要给节点发消息首先要保证我们和节点联系过,也就是说我们的节点表里可以查到这个节点。 net_kernel要节点的可用性, 会定期发tick消息坚持节点的可达。对端节点也会主动发送nodeup,nodeup等消息,协助维护。 net_ticktime = TickTime Specifies the net_kernel tick time. TickTime is given in seconds. Once every TickTime/4 second, all connected nodes are ticked (if anything else has been written to a node) and if nothing has been received from another node within the last four (4) tick times that node is considered to be down. This ensures that nodes which are not responding, for reasons such as hardware errors, are considered to be down. 节点有2种类型可见的和不可见的。erlang节点是可见的, c_interface写的节点不可见,因为c模块提供的节点能力有限。 erlang进程见通讯可以通过 1. pid 2.进程名称 来进行。 erlang系统很大的威力就在用elang实现了名称和pid的全局性维护。也就是说erlang做了个相当复杂的模块来解决名称失效 重复 查询功能。正常情况下名称是全局行的,也就是erlang的节点是全联通的,可以通过来调整。 auto_connect = Value Specifies when no will be automatically connected. If this parameter is not specified, a node is always automatically connected, e.g when a message is to be sent to that node. Value is one of: never Connections are never automatically connected, they must be explicitly connected. See net_kernel(3). once Connections will be established automatically, but only once per node. If a node goes down, it must thereafter be explicitly connected. See net_kernel(3). erlang实现透明进程通信的关键点在于pid的变换: pid {X,Y,Z} 在发到网络的时候发出去的格式是{sysname, Y, Z} 因为节点之前互相联系过 所以互相知道对方的sysname, 而且sysname在dist_entry里保存,当对端收到dec_pid的时候,用peer sysname 的查到在自己dist_entry里面的索引,然后用这个index 来构造新的pid,即 {index, Y, Z}。 erlang给一个pid发消息的时候, 首先检查Pid是本地的还是外部的, 如果是外部的,则进行上面的变换,然后通过inet_tcp_dist模块,沿着inet_tcp, inet_drv这条线发送出去。 这条消息到达对端的时候 inet_drv首先受到这条消息, 照理说应该提交给inet_tcp, 然后再到inet_tcp_dist, net_kernel来处理.但是erlang为了效率的考虑做了个折中。在inet_drv里面driver_output*中检查消息的类型 如果是dist来的消息,就给erts_net_message来处理。 这个erts_net_message处理以下几个重要消息: #define DOP_SEND 2 #define DOP_EXIT 3 #define DOP_UNLINK 4 #define DOP_NODE_LINK 5 #define DOP_REG_SEND 6 #define DOP_GROUP_LEADER 7 #define DOP_EXIT2 8 #define DOP_SEND_TT 12 #define DOP_EXIT_TT 13 #define DOP_REG_SEND_TT 16 #define DOP_EXIT2_TT 18 #define DOP_MONITOR_P 19 #define DOP_DEMONITOR_P 20 #define DOP_MONITOR_P_EXIT 21 如果是DOP_SEND的话,就把message放到变换好的进程的队列中去。 这个核心的功能,由beam的c模块(dist.c, erl_node_tables.c, io.c )和net_kernel模块一起实现。然后在这底层的原语上进一步实现了如rpc 这样的上层模块,进一步方便了用户. 用erlsnoop http://mryufeng.iteye.com/blog/167695 可以观察到上面的通讯,有助于理解系统的运作。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-12-07
大哥最近发威了,一口气写了这么多blog?是erlang group III的ppt内容吧?哈哈
|
|
返回顶楼 | |
发表时间:2008-12-09
多写点好啊! 这版太冷清了
|
|
返回顶楼 | |
发表时间:2008-12-09
主要是底层关注的人比较少 但是用到的时候比较威力
|
|
返回顶楼 | |
发表时间:2008-12-09
从erlang的这3个特性看来,是不是可以说,用erlang开发一个webserver在多核的情况下性能会比较的高呢,如果用它开发一个webserver,它的性能和lighttpd比会如何(假设开发者水平相当)
在多核的机器上: 如果说erlang比lighttpd慢,那是否能说明erlang只是是在性能和速度上做出的一个平衡 如果erlang比lighttpd快,那我觉得确实erlang在多核上有优势. |
|
返回顶楼 | |
发表时间:2008-12-09
比lighty要差些。 因为erlang是opcode执行的,要比lighty的c慢, 但是架构上的优势可以补偿不少,特别是机器比较高档的话,但是版本升级,稳定度,监控和日志什么的,lighty就没有优势。
|
|
返回顶楼 | |
发表时间:2008-12-09
erlang好像有个bug,在不同机器上的节点可能会产生有相同pid的进程。
|
|
返回顶楼 | |
发表时间:2008-12-09
那不是bug,正常的,pid到另外一台机器以后会变换的,肯定不重复。X,Y,Z 中的本机X是0,区别于外来的PID.
|
|
返回顶楼 | |
发表时间:2008-12-09
重新看了下,那个问题是一个节点崩溃后,重新启动产生的进程id和原来相同。
这个问题的详细描述是在erlang-china提供的一篇文章《编写分布式的erlang程序:陷阱和对策》的4.1节。 |
|
返回顶楼 | |
发表时间:2008-12-09
这样的话是可能的。
|
|
返回顶楼 | |