IT & Engineering

Wie die Node.js-App Cloud Monitoring die Mailgun-API nutzt, um E-Mail-Workflows zu automatisieren

Dieser Beitrag wurde von Dan Di Spaltro, Director of Product bei Rackspace Cloud Monitoring, verfasst. Mit Cloud Monitoring überwachen Sie jeden Server in jedem Rechenzentrum. So stellen Sie jederzeit sicher, dass Ihre Anwendungsinfrastruktur einwandfrei funktioniert. Bevor Dan das Engineering-Team von Cloud Monitoring leitete, war er Mitbegründer von Cloudkick. Das Y-Combinator-Startup, das sich auf die Überwachung von Cloud-Infrastruktur konzentrierte, wurde 2010 von Rackspace übernommen.
Bild für Wie die Node.js-App Cloud Monitoring die Mailgun-API nutzt, um E-Mail-Workflows zu automatisieren

Dieser Beitrag wurde verfasst von Dan Di Spaltro, Director of Product bei Rackspace Cloud Monitoring. Mit Cloud Monitoring überwachen Sie jeden Server in jedem Rechenzentrum. So stellen Sie jederzeit sicher, dass Ihre Anwendungsinfrastruktur einwandfrei funktioniert. Bevor Dan das Engineering-Team von Cloud Monitoring leitete, war er Mitbegründer von Cloudkick. Das Y-Combinator-Startup, das sich auf die Überwachung von Cloud-Infrastruktur konzentrierte, wurde 2010 von Rackspace übernommen. 

Das Engineering-Team bei Rackspace sucht immer nach Wegen, Rackspace-Produkte in den Lösungen einzusetzen, die wir für unsere Kunden entwickeln. Wir sind der Überzeugung, dass wir durch die Nutzung unserer eigenen Produkte bessere Software für unsere Kunden entwickeln, da wir dem Team, das direkt gegenüber sitzt, direktes Feedback geben können. Während der Übernahme von Mailgun durch Rackspace bot sich uns die einmalige Gelegenheit, die neuesten Dienste von Rackspace in unserem Produkt Cloud Monitoring zu testen. Ein großer Teil der Aufgaben von Cloud Monitoring im Fehlerfall besteht darin, eine E-Mail an den Kunden zu senden. Ein Trigger für diese E-Mails wird ausgelöst, wenn die überwachte Website das Zeitlimit überschreitet, mit einem 404-Fehler antwortet oder eine andere nutzerdefinierte Bedingung in Ihrer Alarm-Language erfüllt ist. Als wir Mailgun evaluierten, war unser Ziel, zuverlässige E-Mail-Benachrichtigungen für unsere Kunden zu ermöglichen, anstatt die Details der Erstellung, Zustellung und Analysen von E-Mails zu meistern – drei wesentliche Komponenten der E-Mail-Automatisierung in unserer Größenordnung. Als wir Mailgun ausprobierten, waren wir sehr beeindruckt. Wir erhielten die Vorteile, die wir erwartet hatten, und sogar einige, mit denen wir nicht gerechnet hatten. Beispiel:

  • Vernünftiges Bouncing – Mailgun bietet einen sinnvollen, API-basierten Weg, um mit Bounces umzugehen, die aus vielen verschiedenen Gründen häufig auftreten.
  • Analysen und Tagging – Da wir in unserer Produktionsumgebung ständig Fehlerszenarien testen, brauchten wir eine Möglichkeit, bestimmte Konten zu isolieren, die wir als „besonders“ markiert haben. Mailgun unterteilt alle Berichte basierend auf Tags in Segmente, was das Testen erleichtert.
  • Verantwortlichkeit – Einfach nur eine E-Mail zu versenden, reicht uns nicht aus. Die Logs von Mailgun bieten eine End-to-End-Ansicht dessen, was genau mit jeder E-Mail passiert ist.

Bevor wir uns ansehen, wie wir Mailgun implementiert und ausgerollt haben, werfen wir einen Blick auf die Architektur von Cloud Monitoring

Cloud-Monitoring-Pipeline

Das System von Rackspace Cloud Monitoring ist in eine Pipeline verschiedener Dienste unterteilt. Zur Auffrischung betrachten wir die Architektur aus der Vogelperspektive.

chart

Jeder Schritt repräsentiert einen oder mehrere verteilte Dienste, die durch einen Datenstrom verbunden sind. Wir verwenden die Scribe-Software von Facebook für die Punkt-zu-Punkt-Verteilung, das Routing und das Buffering. Mit diesem Datenstrom können wir die Daten zerteilen, aufbereiten und in jeden beliebigen Bereich unserer Infrastruktur verteilen. Einfaches Experimentieren mit dem Datenstrom ist entscheidend für unsere Geschwindigkeit. Er ermöglicht es uns, Daten überallhin zu senden, und ist ein wesentlicher Bestandteil des Designs, das unsere Hochverfügbarkeit sowie die Beschleunigung und Entwicklung des Produkts unterstützt (Nebenbemerkung: Deshalb trägt das Produkt den Codenamen ELE.).

Vorbereitung auf den Test

Bei einem Produktionssystem ist eine vollständige Umstellung nie eine gute Idee. Daher entschieden wir uns für einen anderen Ansatz. Wir haben Mailgun zunächst schrittweise für Konten eingeführt, die wir für unsere Tests verwenden. Dadurch konnten wir über bloße Mikrovalidierungen und Validierungen von Unit-Tests hinausgehen, um uns mit dem System vertraut zu machen. Dank des unkomplizierten HTTP-Supports in Node.js konnten wir diese Integration zügig umsetzen.

Mocking der Mailgun-API

Wann immer wir eine externe Abhängigkeit hinzufügen, versuchen wir, die API zu mocken, sofern dies machbar ist. Das Mocking einer externen API kann sehr einfach oder sehr aufwendig sein, ist aber dennoch wichtig. Unser Ziel ist es, dem Entwicklungsteam keine zusätzliche Arbeit aufzubürden, aber dennoch Vertrauen in unsere Interaktionen mit einem externen Dienst und dessen Funktionsweise zu behalten. Heutzutage sind die meisten APIs versioniert, sodass größere Änderungen mit einer Versionserhöhung einhergehen. Dies ermöglicht es uns, APIs schnell und zuverlässig zu mocken, um umfangreichere End-to-End-Tests in einer kontrollierten Umgebung aufzubauen. Nachdem wir festgelegt hatten, wie wir den Test auf unserem Testkonto ausrollen wollten, bauten wir unsere eigene Mailgun-API, wodurch wir uns mit der neuen Integration vertraut machen konnten. Dieser Prozess war extrem einfach. Die Mailgun-API, die für alle ausgehenden Vorgänge und Analysen bereitgestellt wurde, war einfach und unkompliziert zu implementieren. Erst nach dem Mocking erkannten wir, dass es einen Testmodus gibt, um den Versand von E-Mails in einer Sandbox zu testen. Dennoch war dies eine wertvolle Lernerfahrung.

Präziser Austausch

Nach Abschluss der Testvorbereitungen begannen wir mit der Implementierung und der Überwachung der E-Mail-Performance. So wollten wir das Vertrauen gewinnen, dass Mailgun eine Lösung ist, die wir auf breiterer Basis für unsere Nutzer ausrollen können. In der Anwendung Cloud Monitoring ist die Komponente, die die Zustellung einer Warnung sicherstellt, eine komplexe Software mit dem treffenden Namen Messenger. Sie übernimmt verschiedene Aufgaben, um die Zuverlässigkeit unserer E-Mail-Benachrichtigungen zu erhöhen. Intern ist der Messenger eine in Phasen unterteilte Ausführungspipeline. Sie umfasst die folgenden Phasen:

  • Nachricht empfangen
  • Nachrichten-Atom sperren
  • Lookups für Konto/Entität/Prüfung/Alarm durchführen
  • Benachrichtigungsabonnement finden
  • Warnungen zustellen
  • E-Mail erstellen
  • Zustellung
  • Tracken

Während des Tests fügten wir Coding hinzu, um in der Phase zur Warnungszustellung das spezielle Konto zu prüfen, damit das Routing von Nachrichten zu Mailgun gestartet wird. Dieser Prozess war einfach, da nur sehr wenig Coding involviert war. So sieht ein Snippet aus:

                                

                                    if (tenantId === 'XXX') {rn    emailUtil.sendMailgunEmail(address, subject, body, { headers: headers }, function (err, res) {rn        var delta = (Date.now() - startTime);rnrn        accessLog.logAccess(ctx, 'mailgun', misc.getUnixTimestamp(), delta, err);rnrn        if (err) {rn            log.error('error performing email notification', { ctx: ctx, err: err });rn            callback(err);rn            return;rn        }rnrn        callback(null, 'Email successfully sent', body);rn    });rn} else {rn    // ...rn}
                                
                            

Was passiert oben? Zunächst rufen wir die Funktion sendMailgunEmail auf, um die Monitoring-Benachrichtigungs-E-Mail zuzustellen. In unserem Bestreben, ALLES zu messen, messen wir auch die Zeit, die für die Nutzung der Mailgun-API benötigt wird. Zudem gibt es eine Reihe von Wiederholungen, die dieses Coding mit einer Fallback-Option umschließen – eine der bewährten Best Practices, wenn man sich in einer Anwendung auf ein Drittanbietersystem verlässt. Möchten Sie sehen, wie einfach die Funktion sendMailgunEmail ist?

                                

                                    exports.sendMailGunEmail = function(address, subject, body, options, callback) {rn    options = options || {};rn    options.headers = options.headers || {};rn    options.apiUrl = options.apiUrl || settings.MAILGUN_API_URL;rn    options.domain = options.domain || settings.MAILGUN_DOMAIN;rn    options.apiKey = options.apiKey || settings.MAILGUN_API_KEY;rn    options.fromAddress = options.fromAddress || settings.MAILGUN_FROM_ADDRESS;rn    options.testMode = options.testMode || settings.MAILGUN_TEST_MODE;rnrn    var url = options.apiUrl + options.domain + '/messages',rn        bodyObj, k, httpOptions;rnrn    httpOptions = { // 1) set up some defaultsrn        'expected_status_codes': [200],rn        'return_response': true,rn        'parse_json': true,rn        'username': 'api',rn        'password': options.apiKey,rn        'headers': { 'Content-Type': 'application/x-www-form-urlencoded' }rn    };rnrn    bodyObj = {rn        'to': address,rn        'subject': subject,rn        'from': options.fromAddressrn    };rnrn    if (options.isHTML) { // 2) switch based on the content type we want to sendrn        bodyObj.html = body;rn    } else {rn        bodyObj.text = body;rn    }rnrn    for (k in options.headers) { // 3) merge in the headers so we can provide id’s as headers in the emailsrn        if (options.headers.hasOwnProperty(k)) {rn            bodyObj['h:' + k] = options.headers[k];rn        }rn    }rnrn    if (options.testMode) { // 4) enable sandbox testingrn        bodyObj['o:testmode'] = true;rn    }rnrn    if (options.tags) { rn        // 5) set some tags to automatically pivot analytics for visibility.rn        // (we view reporting in the Mailgun control panel but data is also available via API or webhook)rn        bodyObj['o:tag'] = options.tags;rn    }rnrn    body = querystring.stringify(bodyObj);rn    request(url, 'POST', body, httpOptions, callback);rn};
                                
                            

1) Die Request-Funktion abstrahiert den Umgang mit komplexen HTTP-Anfragen sowie die Verarbeitung von Antwortcodes. Dafür werden erwartete Antwortcodes verwendet.

2) Einfacher Umgang mit dem Versand von HTML, der normalerweise ziemlich mühsam ist.

3) Kopfzeilen zusammenführen, was eine einfache Möglichkeit bietet, E-Mails anzureichern. Diese Kopfzeilen ermöglichen es uns, für jeden Nutzer maßgeschneiderte E-Mails zu erstellen, die Details zu seiner Warnung wie alarmId, checkId und tenantId enthalten. Übergeben Sie fast alles in diesen Kopfzeilen, um Ihre E-Mails anzupassen – Informationen, die andernfalls den Textkörper der E-Mail überladen würden.

4) Einfaches Umlegen eines Schalters für den Versand von Test-E-Mails.

5) Benutzerdefinierte Tags ermöglichen das Tracking sowie analytische Facettierungen, die in unseren Produktions-Testszenarien zum Einsatz kommen.

Sehen Sie, wie einfach das war. Wir haben die Erstellung, Zustellung und das Tracking von E-Mails mit Mailgun vollständig automatisiert – etwas, das mit einem traditionellen DIY-Setup schwierig ist.

Zusammenfassung

Der Wechsel zu einem gehosteten Angebot ist für jede Anwendung eine große Entscheidung, insbesondere bei etwas so Kritischem wie E-Mail-Benachrichtigungen. Mit einem rigorosen Testabonnement und dem fantastischen Support des Mailgun-Teams in allen Belangen von der Einrichtung der DKIM-Einträge bis zur API-Integration konnten wir alle E-Mail-Benachrichtigungen für Cloud Monitoring erfolgreich auf Mailgun umstellen. Zusätzlicher Bonus, das Mailgun-Team sitzt direkt neben mir ;). PS: Wir Verstärkung!