2017-10-18 192 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。虽然在实践中,你将不会使用这个标志,并使用更宽的版本跨度 - 它不能保证工作。

相关问题