PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So erstellen Sie eine serverlose GraphQL-API für MySQL, Postgres und Aurora

Ursprünglich am 2. Juli 2019 bei Serverless gepostet

Die Offenlegung einer einfachen Datenbank über eine GraphQL-API erfordert eine Menge benutzerdefinierten Codes und Infrastruktur:richtig oder falsch?

Für diejenigen, die mit „richtig“ geantwortet haben, sind wir hier, um Ihnen zu zeigen, dass das Erstellen von GraphQL-APIs eigentlich ziemlich einfach ist, mit einigen konkreten Beispielen, um zu veranschaulichen, warum und wie.

(Wenn Sie bereits wissen, wie einfach es ist, GraphQL-APIs mit Serverless zu erstellen, gibt es in diesem Artikel auch viel für Sie.)

GraphQL ist eine Abfragesprache für Web-APIs. Es gibt einen wesentlichen Unterschied zwischen einer herkömmlichen REST-API und APIs, die auf GraphQL basieren:Mit GraphQL können Sie mit einer einzigen Anfrage mehrere Entitäten gleichzeitig abrufen. Dies führt zu schnelleren Seitenladevorgängen und ermöglicht eine einfachere Struktur für Ihre Frontend-Apps, was zu einem besseren Weberlebnis für alle führt. Wenn Sie GraphQL noch nie zuvor verwendet haben, empfehlen wir Ihnen, sich dieses GraphQL-Tutorial für eine schnelle Einführung anzusehen.

Das Serverless-Framework eignet sich hervorragend für GraphQL-APIs:Mit Serverless müssen Sie sich keine Gedanken über das Ausführen, Verwalten und Skalieren Ihrer eigenen API-Server in der Cloud machen, und Sie müssen keine Infrastrukturautomatisierungsskripte schreiben. Erfahren Sie hier mehr über Serverless. Darüber hinaus bietet Serverless eine hervorragende herstellerunabhängige Entwicklererfahrung und eine robuste Community, die Sie beim Erstellen Ihrer GraphQL-Anwendungen unterstützt.

Viele Anwendungen in unserer täglichen Erfahrung enthalten Funktionen für soziale Netzwerke, und diese Art von Funktionalität kann wirklich von der Implementierung von GraphQL anstelle des REST-Modells profitieren, wo es schwierig ist, Strukturen mit verschachtelten Entitäten wie Benutzern und ihren Twitter-Beiträgen offenzulegen. Mit GraphQL können Sie einen einheitlichen API-Endpunkt erstellen, mit dem Sie alle benötigten Entitäten mit einer einzigen API-Anfrage abfragen, schreiben und bearbeiten können.

In diesem Artikel sehen wir uns an, wie man eine einfache GraphQL-API mit Hilfe des Serverless-Frameworks Node.js und einer von mehreren gehosteten Datenbanklösungen erstellt, die über Amazon RDS verfügbar sind:MySQL, PostgreSQL und die MySQL-Workalike Amazon Aurora.

Folgen Sie diesem Beispiel-Repository auf GitHub und lassen Sie uns eintauchen!

Erstellen einer GraphQL-API mit einem relationalen DB-Backend

In unserem Beispielprojekt haben wir uns entschieden, alle drei Datenbanken (MySQL, PostgreSQL und Aurora) in derselben Codebasis zu verwenden. Wir wissen, dass das selbst für eine Produktions-App übertrieben ist, aber wir wollten Sie damit umhauen, wie webskalierbar wir bauen. 😉

Aber im Ernst, wir haben das Projekt überfüllt, nur um sicherzustellen, dass Sie ein relevantes Beispiel finden, das auf Ihre Lieblingsdatenbank zutrifft. Wenn Sie Beispiele mit anderen Datenbanken sehen möchten, teilen Sie uns dies bitte in den Kommentaren mit.

Definieren des GraphQL-Schemas

Beginnen wir mit der Definition des Schemas der GraphQL-API, die wir erstellen möchten, was wir in der Datei schema.gql im Stammverzeichnis unseres Projekts unter Verwendung der GraphQL-Syntax tun. Wenn Sie mit dieser Syntax nicht vertraut sind, werfen Sie einen Blick auf die Beispiele auf dieser GraphQL-Dokumentationsseite.

Für den Anfang fügen wir dem Schema die ersten beiden Elemente hinzu:eine Benutzerentität und eine Beitragsentität, die wie folgt definiert werden, sodass jedem Benutzer mehrere Beitragsentitäten zugeordnet werden können:

geben Sie Benutzer {

ein

UUID:Zeichenkette

Name:Zeichenkette

Beiträge:[Beitrag]

}

Geben Sie Post {

ein

UUID:Zeichenkette

Text:Zeichenkette

}

Wir können jetzt sehen, wie die Entitäten User und Post aussehen. Später werden wir sicherstellen, dass diese Felder direkt in unseren Datenbanken gespeichert werden können.

Als Nächstes definieren wir, wie Benutzer der API diese Entitäten abfragen. Während wir die beiden GraphQL-Typen User und Post direkt in unseren GraphQL-Abfragen verwenden könnten, empfiehlt es sich, stattdessen Eingabetypen zu erstellen, um das Schema einfach zu halten. Also fahren wir fort und fügen zwei dieser Eingabetypen hinzu, einen für die Posts und einen für die Benutzer:

Benutzereingabe eingeben {

Name:Zeichenkette

Beiträge:[PostInput]

}

Eingabe PostInput {

Text:Zeichenkette

}

Lassen Sie uns nun die Mutationen definieren – die Operationen, die die in unseren Datenbanken gespeicherten Daten über unsere GraphQL-API modifizieren. Dazu erstellen wir einen Mutationstyp. Die einzige Mutation, die wir jetzt verwenden werden, ist createUser. Da wir drei verschiedene Datenbanken verwenden, fügen wir für jeden Datenbanktyp eine Mutation hinzu. Jede der Mutationen akzeptiert die Eingabe UserInput und gibt eine User-Entität zurück:


Wir möchten auch eine Möglichkeit bieten, die Benutzer abzufragen, also erstellen wir einen Abfragetyp mit einer Abfrage pro Datenbanktyp. Jede Abfrage akzeptiert einen String, der die UUID des Benutzers ist, und gibt die Benutzerentität zurück, die ihren Namen, UUID und eine Sammlung aller zugehörigen Pos``t enthält:

Schließlich definieren wir das Schema und verweisen auf die Abfrage- und Mutationstypen:
schema { query: Query mutation: Mutation }

Wir haben jetzt eine vollständige Beschreibung für unsere neue GraphQL-API! Sie können die gesamte Datei hier sehen.

Handler für die GraphQL-API definieren

Nachdem wir nun eine Beschreibung unserer GraphQL-API haben, können wir den Code schreiben, den wir für jede Abfrage und Mutation benötigen. Wir beginnen mit der Erstellung einer handler.js-Datei im Stammverzeichnis des Projekts, direkt neben der zuvor erstellten schema.gql-Datei.

Die erste Aufgabe von handler.js besteht darin, das Schema zu lesen:



Die typeDefs-Konstante enthält jetzt die Definitionen für unsere GraphQL-Entitäten. Als Nächstes geben wir an, wo der Code für unsere Funktionen gespeichert werden soll. Um die Dinge übersichtlich zu halten, erstellen wir für jede Abfrage und Mutation eine separate Datei:



Die Resolver-Konstante enthält jetzt die Definitionen für alle unsere API-Funktionen. Unser nächster Schritt ist die Erstellung des GraphQL-Servers. Erinnern Sie sich an die oben benötigte graphql-yoga-Bibliothek? Wir verwenden diese Bibliothek hier, um einfach und schnell einen funktionierenden GraphQL-Server zu erstellen:



Schließlich exportieren wir den GraphQL-Handler zusammen mit dem GraphQL Playground-Handler (der es uns ermöglicht, unsere GraphQL-API in einem Webbrowser auszuprobieren):



Okay, wir sind jetzt mit der Datei handler.js fertig. Als nächstes:Code für alle Funktionen schreiben, die auf die Datenbanken zugreifen.

Code für die Abfragen und Mutationen schreiben

Wir brauchen jetzt Code, um auf die Datenbanken zuzugreifen und unsere GraphQL-API zu betreiben. In der Wurzel unseres Projekts erstellen wir die folgende Struktur für unsere MySQL-Resolver-Funktionen, gefolgt von den anderen Datenbanken:


Häufige Abfragen

Im Common-Ordner füllen wir die mysql.js-Datei mit dem, was wir für die createUser-Mutation und die getUser-Abfrage benötigen:eine Init-Abfrage, um Tabellen für Benutzer und Posts zu erstellen, falls sie noch nicht existieren; und eine Benutzerabfrage, um die Daten eines Benutzers zurückzugeben, wenn ein Benutzer erstellt und abgefragt wird. Wir werden dies sowohl in der Mutation als auch in der Abfrage verwenden.

Die Init-Abfrage erstellt sowohl die Benutzer- als auch die Posts-Tabelle wie folgt:


Die getUser-Abfrage gibt den Benutzer und seine Beiträge zurück:

Beide Funktionen werden exportiert; Wir können dann in der Datei handler.js darauf zugreifen.

Mutation schreiben

Zeit, den Code für die createUser-Mutation zu schreiben, die den Namen des neuen Benutzers akzeptieren muss, sowie eine Liste aller Posts, die ihm gehören. Dazu erstellen wir die Datei resolver/Mutation/mysql_createUser.js mit einer einzigen exportierten func-Funktion für die Mutation:


Die Mutationsfunktion muss die folgenden Dinge in dieser Reihenfolge tun:
  1. Stellen Sie mit den Anmeldeinformationen in den Umgebungsvariablen der Anwendung eine Verbindung zur Datenbank her.

  2. Fügen Sie den Benutzer unter Verwendung des Benutzernamens, der als Eingabe für die Mutation bereitgestellt wurde, in die Datenbank ein.

  3. Fügen Sie auch alle mit dem Benutzer verknüpften Beiträge ein, die als Eingabe für die Mutation bereitgestellt werden.

  4. Gibt die erstellten Benutzerdaten zurück.

So erreichen wir das im Code:


Sie können die vollständige Datei, die die Mutation definiert, hier sehen.

Schreiben der Abfrage

Die getUser-Abfrage hat eine ähnliche Struktur wie die Mutation, die wir gerade geschrieben haben, aber diese hier ist noch einfacher. Da sich die getUser-Funktion nun im Common-Namespace befindet, benötigen wir kein benutzerdefiniertes SQL mehr in der Abfrage. Also erstellen wir die Datei resolver/Query/mysql_getUser.js wie folgt:


Sie können die vollständige Abfrage in dieser Datei sehen.

Alles in der serverless.yml-Datei zusammenführen

Gehen wir einen Schritt zurück. Wir haben derzeit Folgendes:

  • Ein GraphQL-API-Schema.

  • Eine handler.js-Datei.

  • Eine Datei für allgemeine Datenbankabfragen.

  • Eine Datei für jede Mutation und Abfrage.

Der letzte Schritt besteht darin, all dies über die Datei serverless.yml miteinander zu verbinden. Wir erstellen eine leere serverless.yml im Stammverzeichnis des Projekts und beginnen mit der Definition des Anbieters, der Region und der Laufzeit. Wir wenden auch die LambdaRole IAM-Rolle (die wir später hier definieren) auf unser Projekt an:


Anschließend definieren wir die Umgebungsvariablen für die Datenbank-Credentials:

Beachten Sie, dass alle Variablen auf den benutzerdefinierten Abschnitt verweisen, der als nächstes kommt und die tatsächlichen Werte für die Variablen enthält. Beachten Sie, dass das Passwort ein schreckliches Passwort für Ihre Datenbank ist und in etwas Sichereres geändert werden sollte (vielleicht p@ssw0rd 😃):

Was sind diese Referenzen nach Fn::GettAtt, fragen Sie? Diese beziehen sich auf Datenbankressourcen:

Die Datei resource/MySqlRDSInstance.yml definiert alle Attribute der MySQL-Instanz. Den vollständigen Inhalt finden Sie hier.

Schließlich definieren wir in der serverless.yml-Datei zwei Funktionen, graphql und Playground. Die graphql-Funktion wird alle API-Anfragen verarbeiten, und der Playground-Endpunkt erstellt eine Instanz von GraphQL Playground für uns, was eine großartige Möglichkeit ist, unsere GraphQL-API in einem Webbrowser auszuprobieren:


Jetzt ist die MySQL-Unterstützung für unsere Anwendung vollständig!

Den vollständigen Inhalt der serverless.yml-Datei finden Sie hier.

Aurora- und PostgreSQL-Unterstützung hinzufügen

Wir haben bereits alle Strukturen geschaffen, die wir benötigen, um andere Datenbanken in diesem Projekt zu unterstützen. Um Unterstützung für Aurora und Postgres hinzuzufügen, müssen wir nur den Code für ihre Mutationen und Abfragen definieren, was wir wie folgt tun:

  1. Fügen Sie eine gemeinsame Abfragedatei für Aurora und für Postgres hinzu.

  2. Fügen Sie die createUser-Mutation für beide Datenbanken hinzu.

  3. Fügen Sie die getUser-Abfrage für beide Datenbanken hinzu.

  4. Fügen Sie der serverless.yml-Datei eine Konfiguration für alle Umgebungsvariablen und Ressourcen hinzu, die für beide Datenbanken benötigt werden.

An diesem Punkt haben wir alles, was wir brauchen, um unsere GraphQL-API bereitzustellen, die von MySQL, Aurora und PostgreSQL unterstützt wird.

Bereitstellen und Testen der GraphQL-API

Die Bereitstellung unserer GraphQL-API ist einfach.

  • Zuerst führen wir npm install aus, um unsere Abhängigkeiten einzurichten.

  • Dann führen wir npm run deploy aus, das alle unsere Umgebungsvariablen einrichtet und die Bereitstellung durchführt.

  • Im Hintergrund führt dieser Befehl die serverlose Bereitstellung in der richtigen Umgebung aus.

Das ist es! In der Ausgabe des Bereitstellungsschritts sehen wir den URL-Endpunkt für unsere bereitgestellte Anwendung. Mit dieser URL können wir POST-Anfragen an unsere GraphQL-API senden, und unser Playground (mit dem wir gleich spielen werden) ist mit GET gegen dieselbe URL verfügbar.

Ausprobieren der API im GraphQL Playground

Der GraphQL Playground, den Sie sehen, wenn Sie diese URL im Browser aufrufen, ist eine großartige Möglichkeit, unsere API auszuprobieren.

Lassen Sie uns einen Benutzer erstellen, indem Sie die folgende Mutation ausführen:

mutation { mysql_createUser( input: { Name: "Cicero" Posts: [ { Text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit." } { Text: "Proin consequat mauris orci, ut consequat purus efficitur vel." } ] } ) { Name UUID } }

In dieser Mutation rufen wir die API mysql_createUser auf, liefern den Text der Beiträge des neuen Benutzers und geben an, dass wir den Namen des Benutzers und die UUID als Antwort zurückerhalten möchten.

Fügen Sie den obigen Text in die linke Seite des Spielplatzes ein und klicken Sie auf die Schaltfläche „Wiedergabe“. Auf der rechten Seite sehen Sie die Ausgabe der Abfrage:



Lassen Sie uns nun nach diesem Benutzer fragen:

query { mysql_getUser(uuid: "f5593682-6bf1-466a-967d-98c7e9da844b") { Name UUID } }

Dies gibt uns den Namen und die UUID des gerade erstellten Benutzers zurück. Sauber!



Wir können dasselbe mit den anderen Backends, PostgreSQL und Aurora, machen. Dazu müssen wir nur die Namen der Mutationen durch postgres_createUser oder aurora_createUser und Abfragen durch postgres_getUser oder aurora_getUser ersetzen. Probieren Sie es selbst aus! (Denken Sie daran, dass die Benutzer nicht zwischen den Datenbanken synchronisiert werden, sodass Sie nur Benutzer abfragen können, die Sie in jeder spezifischen Datenbank erstellt haben.)

Vergleich der MySQL-, PostgreSQL- und Aurora-Implementierungen

Zunächst einmal sehen Mutationen und Abfragen auf Aurora und MySQL genau gleich aus, da Aurora MySQL-kompatibel ist. Und es gibt nur minimale Codeunterschiede zwischen diesen beiden und der Postgres-Implementierung.

Tatsächlich besteht der größte Unterschied zwischen unseren drei Datenbanken für einfache Anwendungsfälle darin, dass Aurora nur als Cluster verfügbar ist. Die kleinste verfügbare Aurora-Konfiguration enthält immer noch eine Nur-Lese- und eine Schreibreplik, sodass wir selbst für diese grundlegende Aurora-Bereitstellung eine Cluster-Konfiguration benötigen.

Aurora bietet eine schnellere Leistung als MySQL und PostgreSQL, hauptsächlich aufgrund der SSD-Optimierungen, die Amazon an der Datenbank-Engine vorgenommen hat. Wenn Ihr Projekt wächst, werden Sie wahrscheinlich feststellen, dass Aurora im Vergleich zu den standardmäßigen MySQL- und PostgreSQL-Konfigurationen eine verbesserte Datenbankskalierbarkeit, einfachere Wartung und höhere Zuverlässigkeit bietet. Aber Sie können einige dieser Verbesserungen auch an MySQL und PostgreSQL vornehmen, wenn Sie Ihre Datenbanken optimieren und Replikation hinzufügen.

Für Testprojekte und Playgrounds empfehlen wir MySQL oder PostgreSQL. Diese können auf db.t2.micro-RDS-Instances ausgeführt werden, die Teil des kostenlosen Kontingents von AWS sind. Aurora bietet derzeit keine db.t2.micro-Instances an, daher zahlen Sie etwas mehr, um Aurora für dieses Testprojekt zu verwenden.

Ein letzter wichtiger Hinweis

Denken Sie daran, Ihre serverlose Bereitstellung zu entfernen sobald Sie mit dem Ausprobieren der GraphQL-API fertig sind, damit Sie nicht weiter für Datenbankressourcen bezahlen, die Sie nicht mehr verwenden.

Sie können den in diesem Beispiel erstellten Stapel entfernen, indem Sie npm run remove im Stammverzeichnis des Projekts ausführen.

Viel Spaß beim Experimentieren!

Zusammenfassung

In diesem Artikel haben wir Sie durch die Erstellung einer einfachen GraphQL-API geführt, die drei verschiedene Datenbanken gleichzeitig verwendet; Obwohl dies in der Realität nicht der Fall ist, konnten wir einfache Implementierungen der Aurora-, MySQL- und PostgreSQL-Datenbanken vergleichen. Wir haben gesehen, dass die Implementierung für alle drei Datenbanken in unserem einfachen Fall ungefähr gleich ist, abgesehen von geringfügigen Unterschieden in der Syntax und den Bereitstellungskonfigurationen.

Das vollständige Beispielprojekt, das wir verwendet haben, finden Sie in diesem GitHub-Repo. Der einfachste Weg, mit dem Projekt zu experimentieren, besteht darin, das Repo zu klonen und es von Ihrem Computer aus mit npm run deploy bereitzustellen.

Weitere GraphQL-API-Beispiele mit Serverless finden Sie im serverless-graphql-Repo.

Wenn Sie mehr über das Ausführen von serverlosen GraphQL-APIs in großem Maßstab erfahren möchten, wird Ihnen vielleicht unsere Artikelserie „Ausführen eines skalierbaren und zuverlässigen GraphQL-Endpunkts mit Serverless“ gefallen

Vielleicht ist GraphQL einfach nicht Ihr Ding und Sie möchten lieber eine REST-API bereitstellen? Wir sind für Sie da:In diesem Blogpost finden Sie einige Beispiele.

Fragen? Kommentieren Sie diesen Beitrag oder erstellen Sie eine Diskussion in unserem Forum.

Ursprünglich veröffentlicht unter https://www.serverless.com.