Erlang節點互聯筆記

最近工做上須要,遊戲服須要部署到騰訊雲上。打算只是登錄充值相關的部署在騰訊雲上,其餘遊戲節點則在另外雲上。實際操做下來,發現Erlang節點並不能很好的互聯起來,節點只能從騰訊雲上主動往外鏈接,反過來則不行。之前以爲理所固然的事情,如今卻變得莫名其妙,因此也趁機稍微深刻了解下這機制。html

Q:請求鏈接遠程節點時,節點互聯是創建一條tcp連接?誰是S,誰是C?node

A:騰訊雲上的測試得出是誰主動鏈接,誰就是C。 節點互聯是創建一條tcp鏈接,主動鏈接者是client,被鏈接的監聽端口就是節點端口 同時節點啓動時自己也會創建一個鏈接到EPMD上,用於獲取、更新節點信息shell

根據實驗結果去看代碼 net_sup進程樹windows

  • <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。服務器

被動鏈接方:cookie

inet_tcp_dist 啓動監聽端口,來接收其餘節點的鏈接。通過握手協議時,會想sys_dist標記節點爲pending,當握手成功後,則改成UP狀態。 (注:中間忽略了其餘各類鏈接狀況下的狀態轉換以及處理)app

回到一開始的問題,爲何只能從騰訊雲上主動外網創建鏈接?由於開放平臺 tgw 的某種奇葩設計,從外部連入的 tcp 鏈接都會多出一個莫名其妙的包頭。若是鏈接後不首先發送此包頭,則沒法正確路由到對應的服務器,同時還需服務器去處理這多出來的包頭。除非去修改Erlang底層的鏈接代碼,不然外網是不可能直接鏈接上來的。tcp

Q:在查詢資料,閱讀代碼過程當中,都會以爲Erlang這套機制安全性不太可靠的。節點互聯靠cookie來驗證,除此以外還有沒有其餘手段來進一步限制呢?測試

A:

關於定製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環境來執行便可。(注:不能徹底相信別人寫的東西,仍是本身去實際操做才能檢驗出來,同時結合源碼也能知道寫文檔上所沒講述的內容)

參考資料

相關文章
相關標籤/搜索