请注意,在读这,你应该真的找到一种方法来更新现有服务,以跟上较新的运行时间。我已经处理了被遗留在传统运行时间上的问题,只是因为有人认为他们需要在某处以某种方式分发某个特定模块,这使得无法升级 - 这只是一场噩梦。
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 –