2017-10-18 231 views
2

我正在嘗試將Apple的voip推送通知添加到我們的應用中。我們的後端提供程序由Erlang的Ejabberd服務器和apns4erl服務器1.0.4編寫。是否有可能同時運行不同的Erlang OTP版本?

目前,apns4erl 2有能力發送voip推送通知。但它需要OTP 19+編譯,我們的系統在OTP 17.3上運行。

所以我可能知道是否可以同時運行這兩個OTP?我無法將OTP升級到19+。新圖書館需要19+。

是否有很好的方法來使這個要求成爲可能,或者我需要將新庫移植到我們的舊庫?

感謝,

埃裏克

+0

順便說一句,我看到你的個人資料。臺灣? 「你好!」隔壁 - 我在沖繩! '(^。^)/' – zxq9

+1

感謝您的幫助。我會嘗試。我是Erlang的新手,需要學習的東西太多了。真的非常感謝你的幫助。^_^..沖繩島是個好地方,我的許多朋友都喜歡那裏,但我從未去過那裏。希望有一天我能和家人一起去那裏做一個職業。 –

+0

最近,我發現了一種連接到現有節點的新方法。選項-remsh可以執行相同的操作,例如:erl -sname client -remsh ejabberd @ new server-api-001 –

回答

4

請注意,在讀這,你應該真的找到一種方法來更新現有服務,以跟上較新的運行時間。我已經處理了被遺留在傳統運行時間上的問題,只是因爲有人認爲他們需要在某處以某種方式分發某個特定模塊,這使得無法升級 - 這只是一場噩夢。

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表格更好地執行

+0

嗨zxq9,RPC代碼確實爲我當前的問題工作。但是目前,我在OTP 20.1上創建了新節點,並在OTP 17.3上創建了舊節點。事實上,在我目前的測試中它工作得很好。從節點17發送到20的呼叫非常簡單,只是從OTP17發送到OTP 20的記錄數據。但根據您的&legoscia的評論,當創建OTP 20節點時,+ R選項似乎是必需的。有什麼我可以檢查我的OTP 20 + OTP 17系統的能力問題嗎? –

3

zxq9's answer涵蓋了您需要了解的特殊情況。我只想提+R標誌:

+R ReleaseNumber
設置兼容模式。

默認情況下,分配機制不向後兼容。該標誌將仿真器設置爲兼容模式,並且具有較早的Erlang/OTP版本ReleaseNumber。版本號必須在<current release>-2..<current release>的範圍內。這限制了仿真器,使其可以與運行早期版本的Erlang節點(以及C和Java節點)進行通信。


確保分佈式系統的Erlang的所有節點(Erlang-,C-,和Java節點)是相同的Erlang/OTP釋放的,或由兩種不同的Erlang/OTP釋放X和Y,其中所有Y節點具有兼容模式X.

請參閱the erl man page。雖然在實踐中,你將不會使用這個標誌,並使用更寬的版本跨度 - 它不能保證工作。

相關問題