請注意,在讀這,你應該真的找到一種方法來更新現有服務,以跟上較新的運行時間。我已經處理了被遺留在傳統運行時間上的問題,只是因爲有人認爲他們需要在某處以某種方式分發某個特定模塊,這使得無法升級 - 這只是一場噩夢。
TL; DR(但你無論如何都應該讀它)
是的,我剛剛確認,你可以通過disterl連接的R17和R20節點和發送消息:
R17節點:
[email protected]:/opt/erlang/R17.5/bin$ ./erl -name bar -cookie walnut
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.4 (abort with ^G)
([email protected])1> P = spawn(fun Wait() -> receive {From, Message} -> From ! {received, Message}, Wait() end end).
<0.44.0>
([email protected])2> global:register_name(waiter, P).
yes
R20節點:
[email protected]:~$ erl -name foo -cookie walnut
Erlang/OTP 20 [RELEASE CANDIDATE 2] [erts-9.0] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.0 (abort with ^G)
([email protected])1> net_kernel:connect('[email protected]').
true
([email protected])2> global:send(waiter, {self(), "blah blah blah"}).
<7489.44.0>
([email protected])3> flush().
Shell got {received,"blah blah blah"}
ok
請注意,在R20節點上方啓動了第一個,因此這是正在運行的EPMD的版本。我不知道這是否重要,我也不知道EPMD是否在R17和R20之間發生了變化。
這是所有未公開的功能。閱讀下面的很多更具前瞻性的方式來做到這一點。
連接不同版本的兩個節點的文檔化方式是使用+R
運行時標誌。我認爲這是一種非常不可靠的黑客攻擊(正如我上面演示的那樣不可靠),除非您已經首先徹底地進行了測試 - 並且根據所涉及的版本可能會產生意想不到的副作用(並且不知道將來會發生什麼)。但這是一個實際的運行時間標誌,它顯然存在的原因。有關詳細信息,請參閱legoscia's answer。
討論
無論Erlang的運行時的兩個版本都超過disterl兼容,在二郎山寫網絡應用是很容易。你可以通過TCP連接任何不同的東西。
簡單的解決方案是使用當前版本的Erlang(R20)在Erlang中編寫網絡應用程序。1),接收Apple voip推送,並將它們轉發給您的主應用程序。
寫:
- 單個TCP套接字處理您的R17系統內部處理。
- R20中的Apple VOIP推送服務處理程序和與R17 TCP套接字處理程序對話的TCP套接字連接進程。
將您的系統中的Apple VOIP服務視爲您的應用程序的本地部分。 VOIP服務在R17節點中的套接字處理器是。確保你在編寫接口函數時考慮到這一點 - 稍後如果你可以將你的代碼遷移到R20,那麼你就不必擔心這個細節,因爲它已經被Erlang的內部協議抽象了。
至於推送更新自己,你可以創建任何你想要的協議。
Erlang的external term format沒有R17和R20之間變化,所以你就可以通過具有蘋果VOIP側插座處理器(R20的節點上)發送兩個節點之間的本地消息做這樣的事情:
notify_node(Socket, VOIP_Data) ->
Message = term_to_binary({push, VOIP_Data}),
ok = gen_tcp:send(Socket, Message),
log(info, "Message sent").
和接收節點(R17的節點):
loop(Parent, Debug, State = #s{socket = Socket}) ->
receive
{tcp, Socket, Bin} ->
{push, VOIP_Data} = binary_to_term(Bin, [safe]),
{ok, NewState} = do_stuff(VOIP_Data, State)
loop(Parent, Debug, NewState);
%% Your other stuff
%% OTP system stuff
end.
你可以寫R17側作爲gen_server也,聽:
handle_info({tcp, Socket, Bin}, State = #s{socket = Socket}) ->
%% whatever
我大多數時候經常會看到套接字處理進程爲proc_lib
進程而不是gen_servers。但在大多數情況下並不重要。
另一種方法是使用二進制代碼:
notify_node(Socket, VOIP_Data) ->
Message = <<"PUSH ", VOIP_Data>>,
ok = gen_tcp:send(Socket, Message),
log(info, "Message sent").
和接收節點(R17節點)上:
loop(Parent, Debug, State = #s{socket = Socket}) ->
receive
{tcp, Socket, <<"PUSH ", VOIP_Data/binary>>} ->
{ok, NewState} = do_stuff(VOIP_Data, State)
loop(Parent, Debug, NewState);
%% Your other stuff
%% OTP system stuff
end.
這真的取決於VOIP_Data
性質。如果它本身是一個二進制文件,並且R20蘋果推送服務應該在不檢查它的情況下傳遞它,那麼原始二進制方法很容易。如果R20方將要解釋該消息並將其轉換爲它自己的Erlang消息,那麼您將使用binary_to_term/1
/term_to_binary/2
表格更好地執行多。
順便說一句,我看到你的個人資料。臺灣? 「你好!」隔壁 - 我在沖繩! '(^。^)/' – zxq9
感謝您的幫助。我會嘗試。我是Erlang的新手,需要學習的東西太多了。真的非常感謝你的幫助。^_^..沖繩島是個好地方,我的許多朋友都喜歡那裏,但我從未去過那裏。希望有一天我能和家人一起去那裏做一個職業。 –
最近,我發現了一種連接到現有節點的新方法。選項-remsh可以執行相同的操作,例如:erl -sname client -remsh ejabberd @ new server-api-001 –