Ich entwerfe eine Webanwendung und frage mich, wie ich die Architektur für das Versenden automatisierter E-Mails entwerfen soll.
Derzeit ist diese Funktion in meine Web-App integriert, und die E-Mails werden basierend auf Benutzereingaben / Interaktionen gesendet (z. B. beim Erstellen eines neuen Benutzers). Das Problem ist, dass die direkte Verbindung zu einem Mailserver einige Sekunden dauert. Wenn ich meine Bewerbung vergrößere, wird dies in Zukunft ein bedeutender Flaschenhals sein.
Was ist der beste Weg, um das Versenden einer großen Anzahl automatisierter E-Mails innerhalb meiner Systemarchitektur zu verwalten?
Es werden nicht viele E-Mails gesendet (maximal 2000 pro Tag). E-Mails müssen nicht sofort gesendet werden, eine Verzögerung von bis zu 10 Minuten ist in Ordnung.
Update: Die Nachrichtenwarteschlange wurde als Antwort angegeben, aber wie würde dies gestaltet sein? Würde dies in der App erledigt und in einer ruhigen Zeit verarbeitet, oder muss ich eine neue "Mail-App" oder einen neuen Webdienst erstellen, um nur die Warteschlange zu verwalten?
Antworten:
Der übliche Ansatz ist, wie Ozz bereits erwähnte , eine Nachrichtenwarteschlange . Aus Entwurfssicht ist eine Nachrichtenwarteschlange im Wesentlichen eine FIFO-Warteschlange , bei der es sich um einen ziemlich grundlegenden Datentyp handelt:
Das Besondere an einer Nachrichtenwarteschlange ist, dass Ihre Anwendung zwar für das Einreihen in die Warteschlange verantwortlich ist, ein anderer Prozess jedoch für das Entfernen der Warteschlange verantwortlich ist. In der Warteschlangensprache ist Ihre Anwendung der Absender der Nachricht (en) und der Prozess der Warteschlangenentfernung der Empfänger. Der offensichtliche Vorteil ist, dass der gesamte Prozess asynchron ist und der Empfänger unabhängig vom Absender arbeitet, solange Nachrichten verarbeitet werden müssen. Der offensichtliche Nachteil ist, dass Sie eine zusätzliche Komponente, den Absender, benötigen, damit das Ganze funktioniert.
Da Ihre Architektur jetzt auf zwei Komponenten basiert, die Nachrichten austauschen, können Sie den ausgefallenen Begriff Interprozesskommunikation verwenden .
Wie wirkt sich das Einführen einer Warteschlange auf das Design Ihrer Anwendung aus?
Bestimmte Aktionen in Ihrer Anwendung generieren E-Mails. Das Einführen einer Nachrichtenwarteschlange würde bedeuten, dass diese Aktionen jetzt stattdessen Nachrichten in die Warteschlange verschieben sollten (und nicht mehr). Diese Nachrichten sollten die absolut minimale Menge an Informationen enthalten, die zum Erstellen der E-Mails erforderlich sind, wenn Ihr Empfänger sie verarbeiten kann.
Format und Inhalt der Nachrichten
Das Format und der Inhalt Ihrer Nachrichten liegen ganz bei Ihnen, aber Sie sollten bedenken, je kleiner desto besser. Ihre Warteschlange sollte so schnell wie möglich beschrieben und verarbeitet werden können. Wenn Sie einen Großteil der Daten darauf werfen, entsteht wahrscheinlich ein Engpass.
Darüber hinaus unterliegen mehrere Cloud-basierte Warteschlangendienste Einschränkungen hinsichtlich der Nachrichtengröße und können größere Nachrichten aufteilen. Sie werden es nicht bemerken, die geteilten Nachrichten werden als eine Nachricht zugestellt, wenn Sie danach fragen, aber Ihnen werden mehrere Nachrichten in Rechnung gestellt (vorausgesetzt natürlich, Sie verwenden einen Dienst, für den eine Gebühr erforderlich ist).
Design des Empfängers
Da es sich um eine Webanwendung handelt, ist ein einfacher Ansatz für Ihren Empfänger ein einfaches Cron-Skript. Es würde alle
x
Minuten (oder Sekunden) laufen und es würde:n
Anzahl von Nachrichten aus der Warteschlange,Beachten Sie, dass ich Pop anstelle von Get oder Fetch sage. Dies liegt daran, dass Ihr Empfänger die Elemente nicht nur aus der Warteschlange abruft, sondern auch löscht (dh aus der Warteschlange entfernt oder als verarbeitet markiert). Wie genau dies geschehen wird, hängt von Ihrer Implementierung der Nachrichtenwarteschlange und den spezifischen Anforderungen Ihrer Anwendung ab.
Natürlich beschreibe ich im Wesentlichen eine Stapeloperation , die einfachste Art, eine Warteschlange zu verarbeiten. Abhängig von Ihren Anforderungen möchten Sie Nachrichten möglicherweise komplizierter verarbeiten (dies würde auch eine kompliziertere Warteschlange erfordern).
Der Verkehr
Ihr Empfänger kann den Datenverkehr berücksichtigen und die Anzahl der von ihm verarbeiteten Nachrichten basierend auf dem Datenverkehr zum Zeitpunkt der Ausführung anpassen. Ein vereinfachter Ansatz wäre, Ihre hohen Verkehrsstunden basierend auf früheren Verkehrsdaten vorherzusagen und davon auszugehen, dass Sie ein Cron-Skript verwendet haben, das jede
x
Minute ausgeführt wird. Sie könnten so etwas tun:Ein sehr naiver und schmutziger Ansatz, aber er funktioniert. Wenn dies nicht der Fall ist, besteht der andere Ansatz darin, den aktuellen Datenverkehr Ihres Servers bei jeder Iteration zu ermitteln und die Anzahl der Prozesselemente entsprechend anzupassen. Bitte nicht mikrooptimieren, wenn dies nicht unbedingt erforderlich ist. Sie würden Ihre Zeit verschwenden.
Warteschlangenspeicher
Wenn Ihre Anwendung bereits eine Datenbank verwendet, ist eine einzelne Tabelle die einfachste Lösung:
Es ist wirklich nicht komplizierter. Sie können es natürlich so kompliziert machen, wie Sie es benötigen. Sie können beispielsweise ein Prioritätsfeld hinzufügen (was bedeuten würde, dass dies keine FIFO-Warteschlange mehr ist, aber wenn Sie es tatsächlich benötigen, wen interessiert das?). Sie können es auch einfacher machen, indem Sie das verarbeitete Feld überspringen (aber dann müssten Sie Zeilen löschen, nachdem Sie sie verarbeitet haben).
Eine Datenbanktabelle wäre ideal für 2000 Nachrichten pro Tag, würde sich jedoch wahrscheinlich nicht gut für Millionen von Nachrichten pro Tag skalieren lassen. Es sind eine Million Faktoren zu berücksichtigen. Alles in Ihrer Infrastruktur spielt eine Rolle für die Gesamtskalierbarkeit Ihrer Anwendung.
Unter der Annahme, dass Sie die datenbankbasierte Warteschlange bereits als Engpass identifiziert haben, besteht der nächste Schritt in jedem Fall darin, einen Cloud-basierten Dienst zu betrachten. Amazon SQS ist der einzige Dienst, den ich verwendet habe und der das getan hat, was er verspricht. Ich bin mir sicher, dass es da draußen einige ähnliche Dienste gibt.
Speicherbasierte Warteschlangen sind ebenfalls zu berücksichtigen, insbesondere bei kurzlebigen Warteschlangen. memcached eignet sich hervorragend als Speicher für Nachrichtenwarteschlangen.
Unabhängig davon, auf welchem Speicher Sie Ihre Warteschlange aufbauen möchten, sollten Sie intelligent und abstrakt sein. Weder Ihr Absender noch Ihr Empfänger sollten an einen bestimmten Speicher gebunden sein, da sonst ein späterer Wechsel zu einem anderen Speicher eine vollständige PITA wäre.
Realer Ansatz
Ich habe eine Nachrichtenwarteschlange für E-Mails erstellt, die Ihrer Arbeit sehr ähnlich ist. Es war ein PHP-Projekt und ich habe es um Zend Queue herum erstellt , eine Komponente des Zend Frameworks, die mehrere Adapter für verschiedene Speicher bietet . Meine Speicher wo:
Meine Nachrichten waren so einfach wie möglich. Meine Anwendung erstellte kleine Arrays mit den wesentlichen Informationen (
[user_id, reason]
). Der Nachrichtenspeicher war eine serialisierte Version dieses Arrays (zuerst war es das interne Serialisierungsformat von PHP, dann JSON, ich erinnere mich nicht, warum ich gewechselt habe). Dasreason
ist eine Konstante und natürlich habe ich irgendwo eine große Tabelle, diereason
ausführlichere Erklärungen enthält (ich habe es geschafft, etwa 500 E-Mails an Kunden mit der kryptischenreason
anstelle der vollständigeren Nachricht einmal zu senden ).Weiterführende Literatur
Standards:
Werkzeuge:
Interessante liest:
quelle
Sie benötigen eine Art Warteschlangensystem.
Eine einfache Möglichkeit könnte darin bestehen, in eine Datenbanktabelle zu schreiben und andere externe Anwendungsprozesszeilen in dieser Tabelle zu haben. Sie können jedoch auch viele andere Warteschlangentechnologien verwenden.
E-Mails können wichtig sein, sodass bestimmte E-Mails fast sofort ausgeführt werden (z. B. Zurücksetzen des Kennworts), und E-Mails mit geringerer Bedeutung können für einen späteren Versand zusammengefasst werden.
quelle
Neben der Warteschlange sollten Sie auch E-Mails über spezialisierte Dienste senden: MailChimp zum Beispiel (ich bin nicht mit diesem Dienst verbunden). Andernfalls senden viele Mail-Dienste wie Google Mail Ihre Briefe bald in einen Spam-Ordner.
quelle
Ich habe mein Warteschlangensystem in verschiedenen 2 Tabellen wie folgt modelliert:
Es gibt 1-1 Beziehung zwischen diesen Tabellen.
Nachrichtentabelle zum Speichern des Nachrichteninhalts. Der tatsächliche Inhalt (An, CC, BCC, Betreff, Text usw.) wird im XML-Format in das Diagrammfeld serialisiert. Andere Von, Bis-Informationen werden nur zum Melden von Problemen verwendet, ohne das Diagramm zu deserialisieren. Durch das Trennen dieser Tabelle können Tabelleninhalte auf einen anderen Festplattenspeicher partitioniert werden. Sobald Sie bereit sind, eine Nachricht zu senden, müssen Sie alle Informationen lesen. Daher ist es nichts Falsches, den gesamten Inhalt in eine Spalte mit Primärschlüsselindex zu serialisieren.
MessageState- Tabelle zum Speichern des Status des Nachrichteninhalts mit zusätzlichen datumsbasierten Informationen. Das Trennen dieser Tabelle ermöglicht einen schnellen Zugriff auf den Mechanismus mit zusätzlichen Indizes für den schnellen E / A-Speicher. Andere Spalten sind bereits selbsterklärend.
Sie können einen separaten Thread-Pool verwenden, der diese Tabellen durchsucht. Wenn sich Anwendung und Pool auf demselben Computer befinden, können Sie eine EventWaitHandle- Klasse verwenden, um dem Pool von der Anwendung zu signalisieren, dass etwas in diese Tabellen eingefügt wurde. Andernfalls ist ein periodischer Scan mit einer Zeitüberschreitung am besten.
quelle