So erstellen Sie ein REAL-Chat-System für Ihr Startup

Jeden zweiten Tag sehe ich einen Blogbeitrag darüber, wie man mit WebSockets ein Chat-System erstellt oder wie man mit der Magie von Firebase ein majestätisches Chat-System erstellt.

Betrachten wir nun einen komplizierten Anwendungsfall:
Wir haben ein Produkt, das aus zwei Teilen besteht: 1) eine mobile App, die unsere Endbenutzer installieren, und 2) ein Web-Dashboard. Das Dashboard wird von Administratoren verwendet, um eine bestimmte Zielgruppe anzusprechen und ihnen Nachrichten zu senden. Die ausgewählte Zielgruppe erhält die Nachrichten auf ihren mobilen Apps.

Beachten Sie, dass wir Lösungen für die folgenden Anwendungsfälle bereitstellen müssen:

  • 1–1 Chat zwischen zwei Benutzern
  • Gruppenchats unter Benutzern
  • Senden von Massennachrichten (wir bezeichnen sie als "Kampagnen") vom Dashboard an Benutzer
  • Senden einzelner Nachrichten an einen bestimmten Benutzer über das Dashboard

Kampagnennachrichten sind in folgende Kategorien unterteilt:

  • Der Administrator des Dashboards muss einen Gruppenchat erstellen und eine Zielgruppengruppe hinzufügen.
  • Der Administrator des Dashboards erstellt einzelne Kanäle zwischen dem Dashboard und jedem Benutzer und legt eine Nachricht in diesem Kanal ab. Die Benutzer als Mitglieder erhalten die Nachrichten in ihren mobilen Apps.
  • Der Administrator des Dashboards sendet eine unidirektionale Nachricht an die Benutzer. Der Benutzer erhält die Nachricht entweder per SMS oder im Chat-Format.

Nun stellt sich die Frage, wie dies umgesetzt werden soll.

Lösungen

Eine Lösung besteht darin, das Rad neu zu erfinden. Wir alle haben von Firebase und seiner Größe gehört. Wir können die Echtzeitdatenbank von Firebase verwenden, um unsere eigene Chat-Infrastruktur aufzubauen.

Mal sehen, wie die Implementierung aussieht:

Am Ende erhalten Sie den folgenden Firebase-Baum:

  • campaignMessageQueue
  • campaignQueue
  • campaignStatus
  • chatMessages
  • chatReadReceipts
  • chattet
  • chatTypingIndicators
  • E-Mail Benachrichtigungen
  • messageQueue
  • userChats
  • userPushTokens
  • nonChatSMSQueue
  • campaignMessageQueue

Unheimlich! Ist es nicht so?
Funktioniert es? Ja.
Skaliert es? So'ne Art.
Ist es einfach damit umzugehen? Auf keinen Fall!
Um dieses Biest zu unterstützen, musst du viel Zeit und Energie investieren.
Diese Lösung erfindet jeden Aspekt eines Chat-Systems neu, einschließlich: Lesebestätigungen, Tippindikatoren, Benachrichtigungen und Fallstatus für Chats.
Sie müssen verschiedene Node-Worker einrichten, die aus verschiedenen Warteschlangen in Firebase Tree lesen.

Hier ist eine Beschreibung der einzelnen Mitarbeiter:

campaignWorker

Der Arbeiter arbeitet mit campaignQueue.
Der Mitarbeiter empfängt Aufträge über die Web-Dashboard-Benutzeroberfläche, ruft die Verteilerliste ab, erstellt neue Chats mit Benutzern und platziert die Kampagnennachricht in diesen. Es hat auch die Verantwortung, Jobs in campaignMessageQueue zu erstellen.

messageWorker

Der Worker bearbeitet messageQueue.
Es behandelt alle Benachrichtigungsaufgaben für normale / Nicht-Kampagnen-Nachrichten.

campaignMessageWorker

Der Worker arbeitet mit campaignMessageQueue. Die Funktionalität ist genau wie bei messageWorker, es wird nur eine andere Warteschlange bearbeitet.

nonChatSMSWorker

Der Worker arbeitet mit nonChatSMSQueue.
Es verarbeitet das Senden von reinen SMS-Nachrichten, die keine Nachricht in einem echten Chat erstellen.

campaignMessageWorker

Der Worker arbeitet mit campaignMessageQueue.
Es verarbeitet das Senden von Massennachrichten außerhalb der Kampagne für ein Dashboard.

Klingt nach viel Arbeit, oder? Das Implementieren und Verwalten des gesamten Codes ist nicht das einzige Problem. Manchmal verstopfen die Node-Worker und manchmal stürzen sie ab und müssen neu gestartet werden.
Die Wartungskosten sind so hoch, dass Sie bald nach einer Alternative suchen. Ihr Ziel wird es sein, das Vertrauen in Firebase als Ihre Chat-Datenbank zu beseitigen. Die Frage ist, wie das möglich ist.

Dann kommt Twilio zum Spielen. Sie sind hauptsächlich für ihre SMS-API bekannt, bieten aber auch eine Chat-API.

Twilios programmierbare Chat-API

Programmable Chat ist ein Cloud-basiertes Chat-Produkt, das eine Reihe von Client-SDKs und eine REST-API für die Integration von Chat-Funktionen in Anwendungen und Websites bietet. Es ist dem Extensible Messaging and Presence Protocol (XMPP) nachempfunden und basiert auf dem Konzept der Service Instances. In den Chat-Diensten werden alle Kanäle, Nachrichten, Benutzer und anderen Ressourcen einer Chat-Bereitstellung live angezeigt.

  • Jede Dienstinstanz kann viele Kanäle haben.
  • Jeder Kanal kann viele Mitglieder haben.
  • Jeder Kanal könnte viele Nachrichten haben.

Service-Instanzen sind isolierte Silos und es gibt keine Möglichkeit für zwei verschiedene Service-Instanzen, miteinander zu kommunizieren. So senden Sie eine Nachricht zwischen zwei Entitäten: Zunächst sollte ein Kanal zwischen ihnen vorhanden sein. Dann müssen die Entitäten als Mitglieder zum Channel hinzugefügt werden. Jede im Kanal abgelegte Nachricht wird für die Mitglieder veröffentlicht. Mithilfe von Client-SDKs (verfügbar für Web, iOS und Android) können wir die Liste der abonnierten Kanäle abrufen, zu denen ein Benutzer Mitglied ist (oder zu denen er eingeladen wurde), sobald er sich beim Client anmeldet.
Dieses Modell ist super flexibel.

Kehren wir nun zu dem ursprünglichen Problem zurück, das wir zuvor über Firebase gelöst haben. Wir werden versuchen, es in Twilio umzusetzen:

Zunächst erstellen wir eine Standarddienstinstanz. Diese Dienstinstanz wird vom Dashboard verwendet, um Nachrichten an die mobilen Benutzer zu senden. Außerdem können unsere Benutzer private Nachrichten an den Administrator des Dashboards senden. Alle diese Kanäle befinden sich in dieser Dienstinstanz.

Mit der programmierbaren Chat-API können wir die Abhängigkeit von Firebase vollständig beseitigen. Wir werden die oben genannten Knotenarbeiter entfernen und die Struktur unseres Projekts vereinfachen.

Lassen Sie uns nun über Twilios Chat-REST-API sprechen. Wir können es verwenden, um alle zuvor diskutierten Anwendungsfälle zu implementieren. Die API wird von unserem Backend verwendet und ist für die Systemnutzung vorgesehen. Die API kann verwendet werden, um die Verwendung des programmierbaren Chats zu koordinieren. Sie können Mitglieder hinzufügen, beliebige Nachrichten senden, die Benutzerrolle ändern usw. Grundsätzlich ist dies ein Gott-Modus für unser Chat-System.

Hier ist ein kurzes Detail darüber, wie jedes Szenario implementiert wurde:

  • Benutzer-zu-Benutzer-Chat (mobil): Wenn ein Benutzer einen Chat mit einem anderen Benutzer initiieren muss, sendet der mobile Client eine Anfrage an den angegebenen Endpunkt im Backend. Unser Backend wird versuchen, einen Kanal mit dem eindeutigen Namen [user1.uuid, user2.uuid] .sort.join (‘:’) in der Standarddienstinstanz zu finden. Wird kein Kanal mit diesem eindeutigen Namen gefunden, erstellt unser REST-Client einen neuen Kanal mit diesem Namen und fügt ihm beide Benutzer als Mitglieder hinzu. Der Endpunkt gibt die entsprechende Kanal-ID in der Rücknutzlast an den mobilen Client zurück. Von dort aus kann der mobile Client Nachrichten auf diesem Kanal senden. Mit der REST-API von Twilio stellen wir sicher, dass keine doppelten Kanäle zwischen zwei Benutzern erstellt werden und dass der Verlauf der Konversationen beibehalten wird. Wenn ein Benutzer das nächste Mal eine Nachricht an einen anderen Benutzer senden möchte, wird derselbe Kanal verwendet.
def create_1_to_1_chat (u1, u2)
 unique_name = [u1.uuid, u2.uuid] .sort.join (‘:’)
 name = User.where (uuid: [u1.uuid, u2.uuid] .sort) .map (&: name) .join ('-')
 c = add_channel (eindeutiger_name, name, kanaltyp:: public)
 c = update_attribute (c, Thema, Name)
 add_member (c, u1)
 add_member (c, u2)
 c.sid
Ende

2. Benutzer-Dashboard-Chat (mobil): Der Vorgang ist dem vorherigen Anwendungsfall sehr ähnlich. Der größte Unterschied besteht darin, dass das Backend versucht, den Kanal in der Service-Instanz des Dashboards zu finden oder zu initialisieren (und nicht in der Standard-Service-Instanz):

def create_user_to_dashboard_chat (u)
 c = add_channel (u.uuid, "# {@ dashboard.name”> @ dashboard.name ”> @ dashboard.name"> u.name} - # {@ dashboard.name} # {u.uuid} ")
 c = update_attribute (c, 'topic', @ dashboard.name)
 c = update_attribute (c, 'dashboard_uuid', @ dashboard.uuid)
 add_member (c, u)
 add_member (c, @dashboard, role_sid:: channel_admin)
 res = TwilioChannel.load_channel (@dashboard, c)
 res
Ende

3. Dashboard zum Benutzer-Chat (Web): Manchmal möchten wir eine Nachricht an einen einzelnen Benutzer senden. Die hier verwendete Logik ist genau die gleiche, die wir für den Chat vom Benutzer zum Dashboard verwendet haben.

4. Dashboard-zu-Benutzer (auch bekannt als Kampagnen): Wie bereits erwähnt, mussten zwei verschiedene Arten der Dashboard-zu-Benutzer-Kommunikation unterstützt werden.
Der erste Anwendungsfall ist, wenn das Dashboard einen Gruppenchat mit einigen Benutzern erstellen muss. Die Anfrage wird vom Dashboard zusammen mit der Liste der Suchparameter, die zum Definieren der Zielgruppe verwendet werden müssen, an das Backend gesendet. Das Backend empfängt die Anfrage und erstellt asynchron einen neuen Kanal und fügt die ausgewählte Zielgruppe als Mitglieder zum Kanal hinzu.
Der zweite Anwendungsfall ist, wenn das Dashboard einzelne Kanäle zwischen sich und den mobilen Benutzern öffnen muss. Normalerweise verwendet ein Administrator diesen Kommunikationstyp, um eine Antwort vom Publikum zu fordern. Die Anfrage wird vom Dashboard zusammen mit der Liste der Suchparameter, die zum Definieren der Zielgruppenidentitäten verwendet werden müssen, an das Backend gesendet. Das Backend empfängt die Anfrage und erstellt für jeden Benutzer einen anderen Kanal und fügt diesen Benutzer als Mitglied hinzu. Wir verwenden Sidekiq für eine effiziente Hintergrundverarbeitung.

Webhooks-Ereignisse

Mit programmierbaren Chat-Ereignisrückrufen können Sie bestimmte Ereignisse in Ihrem Back-End-Service überwachen und abfangen. Die zwei Kategorien von Ereignissen sind "Pre-Event" (synchron) und "Post-Event" (asynchron). Wenn ein Rückruf angegeben wird, sendet Twilio eine HTTP-Anfrage an die angegebene Webhook-URL. Diese Anfrage enthält alle relevanten variablen Daten.
Wir haben Callbacks nach dem Ereignis zu Analysezwecken und zum erneuten Hinzufügen verschiedener Dashboards als Mitglieder zu den Channels verwendet. Nach Angaben von docs sind Webhooks nach einem Ereignis „nur benachrichtigen“ und liefern Informationen, nachdem die Aktion abgeschlossen wurde. Im Gegensatz zu Vorereignissen blockieren diese keine Rückrufe, da sie informativ sind.
Wir haben uns speziell auf die Event-Handler onMessageSent und onChannelAdded verlassen.

Einschränkungen

Die programmierbare Chat-API ist noch jung und in Arbeit. Während wir an der Erstellung unserer brandneuen Chat-Erfahrung arbeiteten, hatten wir folgende Einschränkungen:

  • Bei Kampagnen (Massennachrichten, die vom Dashboard initiiert wurden) werden die Admins des Dashboards zunächst nicht als Mitglied zum Channel hinzugefügt. Eine Einschränkung der aktuellen Twilio Chat-API besteht darin, dass eine Entität Mitglied von bis zu 1000 Kanälen sein kann. Laut Twilio ist dies ein weiches Limit, mit dem sie besser skalieren können. Andererseits ist es eine Art Limit. Daher wird das Dashboard nur dann als Mitglied hinzugefügt, wenn eine Nachricht von den mobilen Benutzern eingeht. Diese Einschränkung bedeutet auch, dass wir das Dashboard aus dem Channel entfernen müssen, wenn der Administrator damit fertig ist (Konzept "Offene vs. Geschlossene Channels" weiter oben erwähnt).
  • Derzeit können benutzerdefinierte Attribute für Kanäle und Nachrichten festgelegt werden. obwohl es keine Möglichkeit gibt, über sie abzufragen. Dies ist sehr einschränkend und meiner Meinung nach das wichtigste fehlende Merkmal.
  • Jeder Kanal kann nur bis zu 1000 Mitglieder haben. Um fair zu sein, ich denke, jeder Gruppenchat mit mehr als 20 Mitgliedern ist ein Ort des völligen Chaos. Daher halte ich dies nicht für eine echte Einschränkung.

Fazit

Insgesamt denke ich, dass Twilio den Benutzern eine viel flüssigere Erfahrung beim Aufbau eines Chat-Systems bietet als Firebase.
Langfristig wird ein Chat-System, das mit einem Pub-Sub-Protokoll betrieben wird, hinsichtlich Skalierbarkeit und Wartung der wahre Gewinner sein.
Lassen Sie uns einfach wissen, dass es verschiedene Lösungen für den Aufbau eines Chat-Systems gibt. Wenn Sie sich entscheiden müssen, welche Lösung für Sie besser geeignet ist, erstellen Sie eine Liste mit Vor- und Nachteilen. Das Rad neu zu erfinden ist nicht immer eine schlechte Idee, aber Sie müssen auch die vorhandenen Ressourcen berücksichtigen. Als Startup ist es wichtig, schnell voranzukommen. Jetzt können Sie mit dem richtigen Werkzeug schnell und ohne Qualitätseinbußen voranschreiten.

Ressourcen:
https://www.twilio.com/docs/api/chat/
https://firebase.google.com/