OTP steht für Open Telecom Platform ; So geschah es in der Vergangenheit, weil die Plattform für die Bedürfnisse und das Geld von Ericsson geschaffen wurde . Im Prinzip hat dieser Name jedoch ungefähr so viele Konnotationen für seine Funktionalität wie Äpfel mit Telefonen von durchschnittlicher Qualität.
Das Hauptunterscheidungsmerkmal von OTP ist nach Angaben der Autoren die Fehlertoleranz. Kein Multithreading, kein Darstellermodell, keine umfangreichen Mustervergleichsfunktionen, nicht einmal transparentes Clustering und keine Hot-Code-Upgrades. Fehlertoleranz.
Die virtuelle Maschine von Erlang ist oberflächlich sehr einfach gestaltet: Es gibt eine Reihe von „Prozessen“ (nicht Systemprozesse, Erlang-Prozesse) mit isoliertem Speicher, die Nachrichten austauschen können. Das ist alles. Hier ist, was Joe Armstrong dazu sagte:
In meinem Blog habe ich argumentiert, dass Prozesse sich so ziemlich wie Menschen verhalten sollten. Die Menschen haben private Erinnerungen und tauschen Daten per Nachrichtenübermittlung aus.
- Warum ich Shared Memory nicht mag
Messaging in OTP ist sehr einfach: Ein Prozess sendet eine Nachricht synchron oder asynchron an einen anderen (oder eine Gruppe anderer Prozesse). Dazu müssen Sie jedoch wissen, an wen diese Nachrichten gesendet werden sollen. Das heißt, der Absender ist der Exchange Manager. Aber was ist, wenn wir nur eine Sendung senden und allen interessierten Prozessen ermöglichen möchten, diese Nachricht zu abonnieren?
Ja, dies ist ein normaler PubSub, aber in OTP ist er standardmäßig nicht implementiert. Nun, es spielt keine Rolle, wir haben alle Steine in einer Stunde, um sie auf die Knie zu zwingen. Fangen wir an.
Implementierungsoptionen
Grundsätzlich enthält Elixir ein Registry
, das als Gerüst für pubsub verwendet werden kann . Ein kleiner, selbst erstellter Code, eine saubere Betreuung aller Teilnehmer (ein Supervisor für alle) und fertig. Das einzige Problem ist, dass die Registry
lokal ist und nicht weiß, wie man Cluster bildet. Das heißt, in einer verteilten Umgebung (verteilten Knoten) funktioniert diese Schönheit nicht.
Phoenix.PubSub
gibt es eine verteilte Implementierung von Phoenix.PubSub
, die mit zwei vorgefertigten Implementierungen geliefert wird: Phoenix.PubSub.PG2
und Phoenix.PubSub.Redis
. Nun, Redis
ist eindeutig ein zusätzliches Glied in unserer Kette, aber PG2
, das neben den Erlang-Gruppen von pg2
Prozessen arbeitet, ist es. Auch ohne Boilerplate geht das aber nicht.
Wir haben also alles, um bequeme PubSub- Abonnements in unserer Anwendung einzurichten . Ist es Zeit, einen Texteditor zu öffnen? - Nicht wirklich. Ich dupliziere nicht gerne Code von Projekt zu Projekt, und alles, was ich in einer Bibliothek isolieren kann, wird für die Wiederverwendung isoliert.
Envío
So wurde das Envío
Paket geboren. Da Chatter, wie Sie wissen, keinen Cent wert ist, werden wir mit Anwendungsbeispielen beginnen.
Lokaler Newsletter → Registry
defmodule MyApp.Sub do use Envio.Subscriber, channels: [{MyApp.Pub, :main}] def handle_envio(message, state) do
Das ist im Allgemeinen alles. Es bleibt MyApp.Sub
in unseren Supervisor-Baum zu verschieben, und dieser Prozess beginnt, alle Nachrichten zu empfangen, die mit Funktionen von MyApp.Pub
, die auch nicht mit Code überladen sind.
defmodule MyApp.Pub do use Envio.Publisher, channel: :main def publish(channel, what), do: broadcast(channel, what) def publish(what), do: broadcast(what)
Verteilter Newsletter → PG2
Bei verteilten Systemen, die aus vielen Knoten bestehen, funktioniert diese Methode nicht. Wir müssen in der Lage sein, Nachrichten von anderen Knoten zu abonnieren, und Registry
kein Assistent. Es gibt jedoch PG2
, das dasselbe behaviour
implementiert.
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
Der einzige Unterschied zum obigen eigenständigen Code ist der Parameter manager: :phoenix_pub_sub
, den wir an use Envio.Subscriber
(und use Envio.Publisher
) übergeben, um ein Modul zu erstellen, das auf :pg2
anstelle der lokalen Registry
basiert. Mit diesem Publisher
gesendete Nachrichten sind jetzt auf allen Knoten im Cluster verfügbar.
Bewerbung
Envío
unterstützt die sogenannten Backends . Envio.Slack
wird mit der Envio.Slack
mit der Sie das Senden von Nachrichten an Slack
vereinfachen können. Alles, was für die Anwendung erforderlich ist - senden Sie eine Nachricht an den in der config/prod.exs
konfigurierten Kanal - den Envío
config/prod.exs
Envío
. Hier ist eine Beispielkonfiguration:
config :envio, :backends, %{ Envio.Slack => %{ {MyApp.Pub, :slack} => [ hook_url: {:system, "SLACK_ENVIO_HOOK_URL"} ] } }
Jetzt werden alle Nachrichten, die durch Aufrufen von MyApp.Pub.publish(:slack, %{foo: :bar})
gesendet werden, an den entsprechenden Kanal in Slack gesendet, und zwar in einer MyApp.Pub.publish(:slack, %{foo: :bar})
Formatierung. Um das Senden von Nachrichten an Slack zu beenden, beenden Envio.Slack
einfach den Envio.Slack
Prozess. Weitere Beispiele (z. B. ein Login- IO
) finden Sie in Tests.
Warum kreuzige ich, versuche es selbst.
def deps do [ {:envio, "~> 0.8"} ] end
Gute kommunikation!