Wie entwerfe ich ein skalierbares Benachrichtigungssystem? [geschlossen]

32

Ich muss einen Benachrichtigungssystem-Manager schreiben.

Hier sind meine Anforderungen:

Ich muss in der Lage sein, eine Benachrichtigung auf verschiedenen Plattformen zu senden, die möglicherweise völlig unterschiedlich sind (zum Beispiel muss ich in der Lage sein, entweder eine SMS oder eine E-Mail zu senden).

Manchmal ist die Benachrichtigung für alle Empfänger einer bestimmten Plattform gleich, manchmal jedoch auch eine Benachrichtigung pro Empfänger (oder mehrere) pro Plattform.

Jede Benachrichtigung kann plattformspezifische Nutzdaten enthalten (beispielsweise kann eine MMS einen Ton oder ein Bild enthalten).

Das System muss skalierbar sein , ich muss in der Lage sein, eine sehr große Menge an Benachrichtigungen zu senden, ohne die Anwendung oder den Server zum Absturz zu bringen.

Dies ist ein zweistufiger Prozess. Zunächst kann ein Kunde eine Nachricht eingeben und eine Plattform zum Senden auswählen. Die Benachrichtigung (en) sollten erstellt werden, um sie entweder in Echtzeit oder später zu verarbeiten.

Dann muss das System die Benachrichtigung an den Plattformanbieter senden.


Im Moment habe ich zwar einige, aber ich weiß nicht, wie skalierbar es sein wird oder ob es ein gutes Design ist.

Ich habe über folgende Objekte (in einer Pseudosprache) nachgedacht:

ein generisches NotificationObjekt:

class Notification {
    String                 $message;
    Payload                $payload;
    Collection<Recipient>  $recipients;
}

Das Problem mit den folgenden Objekten ist, was passiert, wenn ich 1.000.000 Empfänger habe? Selbst wenn das RecipientObjekt sehr klein ist, nimmt es zu viel Speicherplatz in Anspruch.

Ich könnte auch eine Benachrichtigung pro Empfänger erstellen, bei einigen Plattformanbietern muss ich diese jedoch im Batch senden, was bedeutet, dass ich eine Benachrichtigung mit mehreren Empfängern definieren muss.

Jede erstellte Benachrichtigung kann in einem dauerhaften Speicher wie einer Datenbank oder einem Redis gespeichert werden.

Wäre es gut, dies später zu aggregieren, um sicherzustellen, dass es skalierbar ist?

Im zweiten Schritt muss ich diese Benachrichtigung verarbeiten.

Aber wie kann ich die Benachrichtigung an den richtigen Plattformanbieter unterscheiden?

Soll ich ein Objekt wie eine MMSNotificationErweiterung verwenden abstract Notification? oder sowas Notification.setType('MMS')?

Um eine Vielzahl von Benachrichtigungen gleichzeitig verarbeiten zu können, ist ein Messaging-Warteschlangensystem wie RabbitMQ möglicherweise das richtige Tool. Ist es?

Es würde mir erlauben, viele Benachrichtigungen in die Warteschlange zu stellen und mehrere Mitarbeiter zu beauftragen, Benachrichtigungen zu öffnen und zu verarbeiten. Aber was ist, wenn ich die Empfänger wie oben gezeigt stapeln muss?

Dann stelle ich mir ein NotificationProcessorObjekt vor, für das ich NotificationHandlerjeweils NotificationHandlerdie Verantwortung übernehmen könnte, den Plattformanbieter zu verbinden und eine Benachrichtigung durchzuführen.

Ich kann auch ein verwenden EventManager, um steckbares Verhalten zu ermöglichen.

Feedbacks oder Ideen?

Vielen Dank für Ihre Zeit.

Hinweis: Ich bin es gewohnt, in PHP zu arbeiten, und es ist wahrscheinlich die Sprache meiner Wahl.


Bearbeiten (gemäß der Antwort von morphunreal)

  • Wie viele Nachrichten pro Sekunde senden Sie? (Definieren Sie aktuelle / anfängliche Ebenen, definieren Sie eine maximale Ebene, die das System verarbeiten soll, bevor es neu gestaltet wird.)
  • Welche Hardware-Einschränkungen hat das System (Speicher, CPU usw. für das System verfügbar)
  • Wie wird die Hardware skaliert (dh es werden mehr Server, Cloud Computing usw. hinzugefügt)?

  • Welche Sprachen / Systeme werden Benachrichtigungen generieren?

Es liegt in meiner alleinigen Verantwortung, die Benachrichtigung programmgesteuert zu erstellen, aber über eine Benutzeroberfläche zu erstellen.

  • Kennt der Generator die Empfänger der Nachricht (?) Oder werden sie auf andere Weise bereitgestellt (dh Geschäftsregeln für bestimmte Alarmtypen gehen an bestimmte Empfänger)?

Es sollte möglich sein, eine Benachrichtigung für einen bestimmten Empfänger, eine Gruppe von Empfängern (z. B. mithilfe eines Tag-Systems) oder für eine gesamte Plattform zu erstellen.

  • Gibt es Geschäftsregeln für das Hinzufügen von CC / BCC / Read-Belegen?

Ja. Beachten Sie, dass dies wirklich plattformspezifisch ist und dass read oder cc nicht auf allen Plattformen verfügbar sind.

  • Kennt der Generator den Typ der Nachricht, die er sendet (dh SMS / E-Mail), oder basiert er auf dem Empfänger?

Sie basiert jedoch auf dem Empfänger. Da der Empfänger plattformbezogen ist und Plattformen unterschiedliche Datenverarbeitungsmethoden verwenden, ist die Benutzeroberfläche wahrscheinlich plattformspezifisch, um die Einrichtung von Bildern, Tönen oder Ähnlichem zu ermöglichen.

  • Benötigt der Generator eine Bestätigung des Versendens / Empfangens / Lesens von Nachrichten (asynchroner oder synchroner Versand)?

Nun, das System sollte fehleranfällig sein, aber wir möchten den Fehler behandeln, um eine Reihe von Regeln zu definieren. Wenn der Server beispielsweise nicht erreichbar ist, sollte die Benachrichtigung für den weiteren Prozess angefordert werden, wenn die Benachrichtigung jedoch falsch ist (oder war) Es sollte nicht in die Warteschlange gestellt, sondern benachrichtigt werden.

  • Gibt es Anforderungen zum Speichern eines Verlaufs von Nachrichtenquellen / -empfängern (wie lange?)

Ja, wir möchten wahrscheinlich einige Statistiken und Berichte erstellen. * Definieren Sie Benachrichtigungsendpunkte


  • Welche Dienste werden zum Senden von Nachrichten verwendet? Hängt davon ab, einige sind klassischer REST-Webservice, andere sind exotische Protokolle, es liegt wirklich am Anbieter.

  • Welche Rückmeldung / Bestätigung wird bereitgestellt (Synchronisierung / Asynchronisierung)

Abhängig davon, sind einige synchron und antworten mit einem Fehler, während andere anschließend abgerufen werden müssen, um nach Fehlern zu suchen.

  • Ist es wahrscheinlich, dass neue Endpunkte hinzugefügt werden (auch wenn dies der Fall ist, muss es sogar abstrahiert werden)?

Ja, tatsächlich wächst unsere App und wir möchten wahrscheinlich einen neuen Anbieter hinzufügen, aber es ist ein Verhältnis von 1 oder 2 pro Jahr.

Trent
quelle
22
Walter, mücke, gbjbaanb, robert harvey, thorsten müller scheinen faul zu sein; Ich sehe keinen Grund, aus dem diese Frage aufgrund eines der folgenden Argumente geschlossen wurde: "Mehrdeutig, vage, unvollständig, zu weit gefasst oder rhetorisch". Eine Designfrage kann keine einfache Frage sein, da sie sehr viele Dinge beinhaltet, obwohl ich der Meinung bin, dass die Ebene dieser Website es ermöglichte, solch komplexe Entscheidungen mit echten Fachleuten zu diskutieren.
Trent
Stellen Sie Fragen, aber stellen Sie keine Fragen! :) Ja, manchmal kann ich auch die Mentalität der Mods nicht verstehen.
Mrchief
upvotes und views zeigen, wie wichtig diese frage ist .... wenn nur moderatoren das verstanden hätten !!!
NoobEditor
Die Verwendung von RabbitMQ ist der richtige Ansatz für dieses Problem. In einem meiner BIG-Unternehmensinterviews wurde mir ein sehr ähnliches Problem gestellt, und ich hatte Probleme mit dem besten fehlertoleranten Publisher- / Abonnentenmuster. Am Ende wurde mir die richtige Antwort gegeben. RabbitMQ. Scheint, als hätten sie das Problem damit gelöst. Hoffentlich hilft das!!!
AkD

Antworten:

16

Teilen Sie zunächst Ihre funktionalen und nicht funktionalen Anforderungen auf und definieren Sie sie sorgfältig. Es ist sehr einfach, ein System zu überdenken, das auf mehrdeutigen Anforderungen basiert.

Beispielsweise sind Ihre nichtfunktionalen Anforderungen an die Skalierbarkeit nicht eindeutig. Es kann eine Menge mentaler Belastungen lindern, wenn Sie tatsächliche Zahlen in Ihr System eingeben. Beispielsweise,

  • Wie viele Nachrichten pro Sekunde senden Sie? (Definieren Sie aktuelle / anfängliche Ebenen, definieren Sie eine maximale Ebene, die das System verarbeiten soll, bevor es neu gestaltet wird.)
  • Welche Hardware-Einschränkungen hat das System (Speicher, CPU usw. für das System verfügbar)
  • Wie wird die Hardware skaliert (dh es werden mehr Server, Cloud Computing usw. hinzugefügt)?

Jetzt, da Ihnen dies nicht mehr im Weg steht, können Sie einige Tests einrichten, um sicherzustellen, dass das Systemdesign / die Systemarchitektur in der Lage ist, Ihre nichtfunktionalen Anforderungen zu erfüllen.

In Bezug auf die geschäftlichen / funktionalen Anforderungen für das Senden von Benachrichtigungen / Nachrichten können die folgenden Hinweise hilfreich sein (wenn Sie weitere Informationen bereitstellen, die ich zu dieser Antwort hinzufügen kann):

Definieren Sie Benachrichtigungsquellen

  • Welche Sprachen / Systeme werden Benachrichtigungen generieren
  • Kennt der Generator die Empfänger der Nachricht (?) Oder werden sie auf andere Weise bereitgestellt (dh Geschäftsregeln für bestimmte Alarmtypen gehen an bestimmte Empfänger)?
  • Gibt es Geschäftsregeln für das Hinzufügen von CC / BCC / Read-Belegen?
  • Kennt der Generator den Typ der Nachricht, die er sendet (dh SMS / E-Mail), oder basiert er auf dem Empfänger?
  • Benötigt der Generator eine Bestätigung des Versendens / Empfangens / Lesens von Nachrichten (asynchroner oder synchroner Versand)?
  • Gibt es Anforderungen zum Speichern eines Verlaufs von Nachrichtenquellen / -empfängern (wie lange?)

Definieren Sie Benachrichtigungsendpunkte

  • Welche Dienste werden zum Senden von Nachrichten verwendet?
  • Welche Rückmeldung / Bestätigung wird bereitgestellt (Synchronisierung / Asynchronisierung)
  • Ist es wahrscheinlich, dass neue Endpunkte hinzugefügt werden (auch wenn dies der Fall ist, muss es sogar abstrahiert werden)?

Ich zögere, ein konkretes Architekturbeispiel anzugeben, da es stark von den Faktoren abhängt. Bei den einfachsten Nachrichtensystemen handelt es sich jedoch häufig um eine einfache Warteschlange, die sich entweder im Arbeitsspeicher / in der Anwendung, in No-SQL, auf der Festplatte oder in einer relationalen Datenbank befindet. Dann kann ein separater Prozess (oder mehrere separate Prozesse, falls verteilt) die Warteschlange nach ihren Nachrichtentypen abfragen [dh nach einem Cron-Job]. und nach Bedarf abschicken.

Dies könnte auch mithilfe einiger Push-basierter Techniken (z. B. PostgreSQL NOTIFY / LISTEN) verbessert werden, wenn Nachrichten sofort gesendet werden müssen.

Der Vorteil einer einfachen Warteschlange besteht darin, dass das System, das die Nachricht generiert, nur wenig Arbeit leistet und das Verarbeitungssystem basierend auf den Hardware- / Leistungsanforderungen ausgeglichen werden kann.

Nathan-m
quelle
Vielen Dank für Ihre Antwort auf die Details, die mir tatsächlich helfen, klarere Ideen zu haben. Ich habe meine Antwort bearbeitet, um die von Ihnen gestellten Fragen zu beantworten.
Trent
-2

Haben Sie das Flyweight-Designmuster für Ihre Benachrichtigungsobjekte berücksichtigt? Ich bin mir da nicht sicher, da ich das Muster nie implementiert habe, aber ich erinnere mich, dass es mit der Aufteilung eines Zustands zwischen den Fliegengewicht-Objekten verbunden ist. Ich denke auch, dass die Mitglieder mit mehr Redundanz größere Auswirkungen hatten, wenn sie geteilt wurden. Es kommt also darauf an, ob Sie nur ein paar Nachrichten an viele Leute senden oder umgekehrt.

Christoph
quelle