2017-10-18 22 views
2

J'essaie d'ajouter la notification push d'Apple dans notre application. Notre fournisseur backend est écrit par le serveur Ejabberd d'Erlang avec le serveur apns4erl 1.0.4.Est-il possible d'exécuter une version différente d'Erlang OTP en même temps?

Actuellement, l'apns4erl 2 a la capacité d'envoyer des notifications push push. Mais il faut compiler OTP 19+ et notre système fonctionne sur OTP 17.3.

Donc, puis-je savoir est-ce possible d'exécuter ces deux OTP en même temps? Je ne peux pas mettre à jour OTP à 19+. Et la nouvelle bibliothèque nécessite 19+.

Existe-t-il un bon moyen de rendre cette exigence possible ou j'ai besoin de porter la nouvelle bibliothèque dans notre ancienne bibliothèque?

Merci,

Eric

+0

Btw, j'ai vu votre profil. Taïwan? "Bonjour!" d'à côté - je suis à Okinawa! '(^. ^) /' – zxq9

+1

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. –

+0

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 –

Répondre

4

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.

+0

Salut zxq9, le code RPC a fonctionné pour mon problème actuel. Mais actuellement, je crée le nouveau noeud sur OTP 20.1 et ancien noeud sur OTP 17.3. En fait, ça fonctionne bien sous mes tests actuels. L'envoi d'un appel depuis les nœuds 17 à 20 est très simple, il suffit d'envoyer des données d'enregistrement de OTP17 à OTP 20. Mais selon votre commentaire de & legoscia, l'option + R semble nécessaire lorsque je crée le nœud OTP 20. Y a-t-il quelque chose que je peux vérifier pour le problème de capacité de mon système OTP 20 + OTP 17? –

3

zxq9's answer couvre tout ce que vous devez savoir pour cette situation particulière. Je veux juste mentionner le drapeau +R:

+R ReleaseNumber
Définit le mode de compatibilité.

Le mécanisme de distribution n'est pas rétrocompatible par défaut. Cet indicateur définit l'émulateur en mode de compatibilité avec une version antérieure Erlang/OTP ReleaseNumber. Le numéro de version doit être compris entre <current release>-2..<current release>.Cela limite l'émulateur, ce qui lui permet de communiquer avec les nœuds Erlang (ainsi qu'avec les nœuds C et Java) qui exécutent cette version antérieure.

Remarque
assurer que tous les noeuds (Erlang-, C-, et des noeuds Java) d'un système Erlang distribué est de la même version Erlang/OTP, ou à partir de deux différentes Erlang/OTP libère X et Y, où tous les noeuds Y ont un mode de compatibilité X.

Voir the erl man page. Bien que dans la pratique, vous n'utiliserez pas ce drapeau et que vous utiliserez des versions plus larges, cela ne fonctionnera pas.