Gardez à l'esprit en lisant ce que vous devriez vraiment trouver un moyen de mettre à jour votre service existant pour maintenir à jour avec les nouveaux runtimes. Je me suis contenté d'être coincé sur un runtime hérité uniquement parce que quelqu'un pensait qu'il fallait fourrer un module particulier quelque part d'une manière qui le rendait impossible à mettre à niveau - et c'était juste un cauchemar.
TL; DR: (Mais vous devriez le lire de toute façon)
Oui, je viens de confirmer que vous pouvez connecter un R17 et un noeud R20 via disterl et envoyer des messages:
noeud 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
noeud 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
Notez qu'au-dessus du nœud R20 a été démarré d'abord, de sorte que c'était la version d'EPMD qui était en cours d'exécution. Je ne sais pas si cela aurait de l'importance, et je ne sais pas si EPMD a changé entre R17 et R20.
Ceci est toutes les fonctionnalités non documentées. Lire ci-dessous pour un beaucoup plus de moyen à l'épreuve du futur pour ce faire.
La méthode documentée pour connecter deux nœuds de versions différentes est avec l'indicateur d'exécution +R
. Je considère ceci comme un hack extrêmement peu fiable (aussi peu fiable que ce que j'ai démontré ci-dessus) à moins que vous ne l'ayez testé en profondeur - et il peut avoir des effets secondaires inattendus selon les versions concernées (et ne pas dire ce qui va arriver). Mais c'est un vrai drapeau d'exécution et il existe évidemment pour une raison. Voir legoscia's answer pour plus de détails à ce sujet.
Discussion
Si oui ou non deux versions du moteur d'exécution de Erlang sont compatibles sur disterl, l'écriture d'applications de réseau en Erlang est vraiment facile. Vous pouvez toujours connecter deux choses différentes sur TCP.
La solution simple à cela serait d'écrire une application réseau dans Erlang en utilisant la version actuelle d'Erlang (R20.1 pour le moment) qui reçoit Apple push voip, et les transmet à votre application principale.
Ecrire:
- Un processus de gestion des sockets TCP unique à l'intérieur de votre système R17.
- Le gestionnaire de services push Apple VOIP dans R20 et un processus de connexion socket TCP qui parle au gestionnaire de socket TCP R17.
Traiter le service VoIP d'Apple au sein de votre système comme si elle existe comme une partie native de votre application. Le gestionnaire de socket dans le nœud R17 est le service VOIP. Assurez-vous d'écrire ses fonctions d'interface dans cet esprit - plus tard, si vous pouvez migrer votre code vers R20, vous n'aurez plus à vous soucier de ce détail car il sera déjà extrait par le protocole interne d'Erlang. En ce qui concerne les mises à jour push elles-mêmes, vous pouvez créer le type de protocole que vous voulez.
Erlang de external term format n'a pas changé entre R17 et R20, donc vous serez en mesure d'envoyer des messages natifs entre les deux noeuds en ayant le gestionnaire de prise côté d'Apple VOIP (sur le noeud R20) faire quelque chose comme:
notify_node(Socket, VOIP_Data) ->
Message = term_to_binary({push, VOIP_Data}),
ok = gen_tcp:send(Socket, Message),
log(info, "Message sent").
Et sur le noeud de réception (le nœud 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.
Vous pouvez écrire le côté R17 comme gen_server aussi, pour écouter:
handle_info({tcp, Socket, Bin}, State = #s{socket = Socket}) ->
%% whatever
Il m'arrive souvent de voir les processus de gestion de socket comme des processus proc_lib
au lieu de gen_servers la plupart du temps. Mais cela n'a pas d'importance dans la plupart des cas.
Une autre approche consiste à utiliser les binaires:
notify_node(Socket, VOIP_Data) ->
Message = <<"PUSH ", VOIP_Data>>,
ok = gen_tcp:send(Socket, Message),
log(info, "Message sent").
Et sur le noeud de réception (le noeud 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.
Cela dépend vraiment de la nature de VOIP_Data
. Si c'est un binaire lui-même et que le service Push Apple R20 doit simplement le transmettre sans l'inspecter, la méthode binaire brute est facile. Si le côté R20 va interpréter le message et le convertir en un message Erlang propre, alors vous ferez beaucoup mieux avec le formulaire binary_to_term/1
/term_to_binary/2
.
Btw, j'ai vu votre profil. Taïwan? "Bonjour!" d'à côté - je suis à Okinawa! '(^. ^) /' – zxq9
Merci de votre aide. Je vais essayer. Je suis un débutant d'Erlang, trop de choses doivent apprendre. Vraiment merci pour votre aide.^_^.. Okinawa est un bon endroit, beaucoup de mes amis aiment là, mais je n'ai jamais été là encore. J'espère qu'un jour je pourrai y aller avec ma famille pour une vocation. –
Récemment, j'ai trouvé une nouvelle façon de me connecter au nœud existant. L'option -remsh peut faire la même chose, ex: erl -sname client -remsh ejabberd @ nouveau serveur-api-001 –