OTP signifie Open Telecom Platform ; donc c'est arrivé historiquement, parce que la plateforme a été créée pour les besoins et pour l'argent d' Ericsson . Mais, en principe, ce nom a à peu près autant de connotations avec sa fonctionnalité que les pommes avec des téléphones de qualité moyenne.
Selon les auteurs, la principale caractéristique distinctive de l' OTP est la tolérance aux pannes. Pas de multithreading, pas de modèle d'acteur, pas de fonctionnalités riches de correspondance de modèles, pas même de clustering transparent et pas de mises à jour de code à chaud. Tolérance aux pannes.
La machine virtuelle Erlang montée en surface est très simple dans sa structure: il existe un tas de «processus» (pas les processus système, les processus Erlang) avec une mémoire isolée qui peuvent échanger des messages. C’est tout. Voici ce que Joe Armstrong a dit à ce sujet:
Dans mon blog, j'ai soutenu que les processus devraient se comporter à peu près comme les gens. Les gens ont des souvenirs privés et échangent des données en passant des messages.
- Pourquoi je n'aime pas la mémoire partagée
La messagerie à l'intérieur d'OTP est très simple: un processus envoie un message à un autre (ou à un groupe d'autres processus), de manière synchrone ou asynchrone. Mais pour cela, vous devez savoir à qui envoyer ces messages. Autrement dit, l'expéditeur est le gestionnaire d'échange. Mais que se passe-t-il si nous voulons simplement envoyer une diffusion et permettre à tous les processus intéressés de s'abonner à ce message?
Oui, c'est un PubSub régulier, mais hors de la boîte dans OTP il n'est pas implémenté. Eh bien, peu importe, nous avons toutes les briques en une heure pour le mettre à genoux. Commençons.
Options d'implémentation
Fondamentalement, Elixir comprend un module de Registry
qui peut être utilisé comme échafaudage pour pubsub . Un petit code homepun, un regard soigné sur tous les participants (un superviseur pour tout le monde), et vous avez terminé. Le seul problème est que le Registry
local et ne sait pas comment se mettre en cluster. Autrement dit, dans un environnement distribué (nœuds distribués), cette beauté ne fonctionnera pas.
Phoenix.PubSub
nous, il existe une implémentation distribuée de Phoenix.PubSub
, qui vient avec deux implémentations prêtes à l'emploi: Phoenix.PubSub.PG2
et Phoenix.PubSub.Redis
. Eh bien, Redis
est clairement un maillon supplémentaire dans notre chaîne, mais PG2
, qui travaille en plus des groupes Erlang de processus pg2
, l'est. En outre, cependant, sans passe-partout ne suffira pas.
Nous avons donc tout pour établir des abonnements PubSub pratiques dans notre application. Est-il temps d'ouvrir un éditeur de texte? "Pas vraiment." Je n'aime pas dupliquer le code d'un projet à l'autre, et tout ce que je peux isoler dans une bibliothèque est isolé pour être réutilisé.
Envío
Ainsi est né le paquet Envío
. Comme le bavardage, comme vous le savez, ne vaut pas un sou, nous allons commencer par des exemples d'utilisation.
Bulletin local → Registry
defmodule MyApp.Sub do use Envio.Subscriber, channels: [{MyApp.Pub, :main}] def handle_envio(message, state) do
C'est, en général, tout. Il reste à MyApp.Sub
dans notre arborescence de superviseur, et ce processus commencera à recevoir tous les messages envoyés à l'aide des fonctions de MyApp.Pub
, qui n'est pas non plus surchargé de code.
defmodule MyApp.Pub do use Envio.Publisher, channel: :main def publish(channel, what), do: broadcast(channel, what) def publish(what), do: broadcast(what)
Newsletter distribuée → PG2
Pour les systèmes distribués composés de nombreux nœuds, cette méthode ne fonctionnera pas. Nous devons être en mesure de souscrire aux messages des autres nœuds, et Registry
pas un assistant ici. Mais il y a PG2
qui implémente le même behaviour
.
defmodule Pg2Sucker do use Envio.Subscriber, channels: ["main"], manager: :phoenix_pub_sub def handle_envio(message, state) do {:noreply, state} = super(message, state) IO.inspect({message, state}, label: "Received") {:noreply, state} end end
La seule différence avec le code autonome ci-dessus est manager: :phoenix_pub_sub
paramètre que nous transmettons pour use Envio.Subscriber
(et use Envio.Publisher
) pour construire un module basé sur :pg2
au lieu du Registry
local. Les messages envoyés à l'aide de cet Publisher
seront désormais disponibles sur tous les nœuds du cluster.
Candidature
Envío
prend en charge les soi-disant backends . Envio.Slack
est livré avec la Envio.Slack
, ce qui vous permet de simplifier l'envoi de messages à Slack
. Tout ce qui est requis de l'application - envoyez un message au canal configuré dans le config/prod.exs
- Envío
fera le Envío
. Voici un exemple de configuration:
config :envio, :backends, %{ Envio.Slack => %{ {MyApp.Pub, :slack} => [ hook_url: {:system, "SLACK_ENVIO_HOOK_URL"} ] } }
Désormais, tous les messages envoyés en appelant MyApp.Pub.publish(:slack, %{foo: :bar})
seront livrés au canal correspondant dans Slack , magnifiquement formatés. Pour arrêter d'envoyer des messages à Slack , arrêtez simplement le processus Envio.Slack
. Plus d'exemples (par exemple, une connexion dans IO
) peuvent être trouvés dans les tests.
Pourquoi je crucifie, essayez-le vous-même.
def deps do [ {:envio, "~> 0.8"} ] end
Bonne communication!