互联笔记"/>
Erlang节点互联笔记
2019独角兽企业重金招聘Python工程师标准>>>
最近工作上需要,游戏服需要部署到腾讯云上。打算只是登陆充值相关的部署在腾讯云上,其他游戏节点则在另外云上。实际操作下来,发现Erlang节点并不能很好的互联起来,节点只能从腾讯云上主动往外连接,反过来则不行。以前觉得理所当然的事情,现在却变得莫名其妙,所以也趁机稍微深入了解下这机制。
Q:请求连接远程节点时,节点互联是建立一条tcp链接?谁是S,谁是C?
A:腾讯云上的测试得出是谁主动连接,谁就是C。 节点互联是建立一条tcp连接,主动连接者是client,被连接的监听端口就是节点端口 同时节点启动时本身也会建立一个连接到EPMD上,用于获取、更新节点信息
根据实验结果去看代码
- <0.21.0>:inet_tcp_dist, 启动时调用erl_epmd向EPMD注册本节点信息
- <0.22.0>:ticker
主动连接方:
net_kernel进程查询sys_dist表连接的节点信息,如果没有,就进入建立连接步骤 inet_tcp_dist:setup,根据对方的节点名获取host,得到对应的IP,然后通过erl_epmd:port_please向对方的EPMD请求该节点的端口信息。并向sys_dist插入该节点信息,标记为pending。Driver:connect(IP, TcpPort, connect_options([{active, false}, {packet, 2}])) 成功后,就进入handshake阶段,详细可以参考Erlang dist protocol部分,代码就略过了。握手成功后,向net_kernel进程发送Kernel ! {self(), {nodeup,Node,Address,publish_type(Flags), true}}。net_kernel即改变节点状态为UP。
被动连接方:
inet_tcp_dist 启动监听端口,来接收其他节点的连接。经过握手协议时,会想sys_dist标记节点为pending,当握手成功后,则改为UP状态。 (注:中间忽略了其他各种连接情况下的状态转换以及处理)
回到一开始的问题,为什么只能从腾讯云上主动外网建立连接?因为开放平台 tgw 的某种奇葩设计,从外部连入的 tcp 连接都会多出一个莫名其妙的包头。如果连接后不首先发送此包头,则无法正确路由到对应的服务器,同时还需服务器去处理这多出来的包头。除非去修改Erlang底层的连接代码,否则外网是不可能直接连接上来的。
Q:在查询资料,阅读代码过程中,都会觉得Erlang这套机制安全性不太可靠的。节点互联靠cookie来验证,除此之外还有没有其他手段来进一步限制呢?
A:
- IP网段限制
- 节点名称限制
- 修改epmd默认端口(只是稍微增加点难度而已,真心要搞,还是防不住)
关于定制EPMD默认端口
- erl -epmd "epmd -port 7000 -daemon" -epmd_port 7000 -name nodename@IP -setcookie 123456
- ERL_EPMD_PORT=7000 erl -name nodename@IP -setcookie 123456
实验得出这两种方式都可以附带启动以指定端口的EPMD,而不需要再另外再执行命令来启动。 第二种只支持shell环境,windows上则需另外安装下shell环境来执行即可。(注:不能完全相信别人写的东西,还是自己去实际操作才能检验出来,同时结合源码也能知道写文档上所没讲述的内容)
参考资料
- EPMD端口定制
- erlang 模块之 epmd
- Erlang epmd的角色以及使用
- epmd文档
转载于:
更多推荐
Erlang节点互联笔记
发布评论