AWS Lambda Funktionen in Amazon Neptune verwenden - Amazon Neptune

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

AWS Lambda Funktionen in Amazon Neptune verwenden

AWS Lambda Funktionen haben viele Verwendungsmöglichkeiten in Amazon Neptune Neptune-Anwendungen. Hier finden Sie allgemeine Anleitungen zur Verwendung von Lambda-Funktionen mit allen gängigen Gremlin-Treibern und Sprachvarianten sowie spezifische Beispiele für Lambda-Funktionen, die in Java, JavaScript und Python geschrieben wurden.

Anmerkung

Die beste Art, Lambda-Funktionen mit Neptune zu verwenden, hat sich mit den letzten Engine-Versionen geändert. Neptune ließ inaktive Verbindungen lange nach der Wiederverwendung eines Lambda-Ausführungskontextes offen, was zu Ressourcenlecks auf dem Server führen konnte. Um dies zu vermeiden, haben wir früher empfohlen, bei jedem Lambda-Aufruf eine Verbindung zu öffnen und zu schließen. Ab Engine-Version 1.0.3.0 wurde der Zeitrahmen (Timeout) für inaktive Verbindungen jedoch reduziert, so dass Verbindungen nicht mehr lecken, nachdem ein inaktiver Lambda-Ausführungskontext wiederverwendet wurde. Daher empfehlen wir jetzt, für die Dauer des Ausführungskontextes eine einzige Verbindung zu verwenden. Dies sollte etwas Fehlerbehandlung und back-off-and-retry Standardcode für den Umgang mit Verbindungen beinhalten, die unerwartet geschlossen werden.

Verwaltung von Gremlin-Verbindungen WebSocket in Funktionen AWS Lambda

Wenn Sie eine Gremlin-Sprachvariante verwenden, um Neptune abzufragen, stellt der Treiber über eine Verbindung eine Verbindung mit der Datenbank her. WebSocket WebSockets sind so konzipiert, dass sie langlebige Client-Server-Verbindungsszenarien unterstützen. AWS Lambda ist dagegen darauf ausgelegt, relativ kurzlebige und zustandslose Hinrichtungen zu unterstützen. Diese Diskrepanz bei der Designphilosophie kann zu unerwarteten Problemen führen, wenn Lambda zur Abfrage von Neptune verwendet wird.

Eine AWS Lambda Funktion wird in einem Ausführungskontext ausgeführt, der die Funktion von anderen Funktionen isoliert. Der Ausführungskontext wird beim ersten Aufruf der Funktion erstellt und kann für nachfolgende Aufrufe derselben Funktion wiederverwendet werden.

Ein einziger Ausführungskontext wird jedoch niemals verwendet, um mehrere gleichzeitige Aufrufe der Funktion zu verarbeiten. Wenn Ihre Funktion gleichzeitig von mehreren Clients aufgerufen wird, erstellt Lambda für jede Instance der Funktion einen zusätzlichen Ausführungskontext. Alle diese neuen Ausführungskontexte können wiederum für nachfolgende Aufrufe der Funktion wiederverwendet werden.

Irgendwann recycelt Lambda Ausführungskontexte, insbesondere wenn sie einige Zeit inaktiv waren. AWS Lambda macht den Lebenszyklus des Ausführungskontextes, einschließlich der Shutdown Phasen Invoke undInit, über Lambda-Erweiterungen verfügbar. Mithilfe dieser Erweiterungen können Sie Code schreiben, der externe Ressourcen wie Datenbankverbindungen bereinigt, wenn der Ausführungskontext wiederverwendet wird.

Eine gängige bewährte Methode besteht darin, die Datenbankverbindung außerhalb der Lambda-Handler-Funktion zu öffnen, so dass sie bei jedem Handler-Aufruf wiederverwendet werden kann. Wenn die Datenbankverbindung irgendwann unterbrochen wird, können Sie die Verbindung innerhalb des Handlers erneut herstellen. Bei dieser Vorgehensweise besteht jedoch die Gefahr von Verbindungslecks. Wenn eine Verbindung im Leerlauf noch lange geöffnet bleibt, nachdem ein Ausführungskontext nicht mehr besteht, können Lambda-Aufrufszenarien mit intermittierenden oder kurzlebigen Lambda-Aufrufen nach und nach Verbindungen verlieren und Datenbankressourcen erschöpfen.

Die Verbindungslimits und Timeout-Werte von Neptune haben sich mit neueren Engine-Versionen geändert. Bisher unterstützte jede Instanz bis zu 60.000 WebSocket Verbindungen. Jetzt variiert die maximale Anzahl gleichzeitiger WebSocket Verbindungen pro Neptune-Instanz je nach Instanztyp.

Außerdem reduzierte Neptune ab der Engine-Version 1.0.3.0 das Leerlauf-Timeout für Verbindungen von einer Stunde auf etwa 20 Minuten. Wenn ein Client eine Verbindung nicht schließt, wird die Verbindung nach einem Leerlauf-Timeout von 20 bis 25 Minuten automatisch geschlossen. AWS Lambda dokumentiert nicht die Lebensdauer des Ausführungskontextes, aber Experimente zeigen, dass das neue Neptune-Verbindungstimeout gut zu inaktiven Lambda-Ausführungskontext-Timeouts passt. Wenn ein inaktiver Ausführungskontext recycelt wird, besteht eine gute Möglichkeit, dass seine Verbindung bereits von Neptune geschlossen wurde oder bald darauf geschlossen werden wird.

Empfehlungen für die Verwendung AWS Lambda mit Amazon Neptune Gremlin

Wir empfehlen jetzt, für die gesamte Lebensdauer eines Lambda-Ausführungskontextes eine einzige Verbindungs- und Graph-Traversal-Quelle zu verwenden, anstatt einer für jeden Funktionsaufruf (jeder Funktionsaufruf verarbeitet nur eine Client-Anfrage). Da gleichzeitige Client-Anfragen von verschiedenen Funktions-Instances verarbeitet werden, die in separaten Ausführungskontexten ausgeführt werden, ist es nicht erforderlich, einen Pool von Verbindungen aufrechtzuerhalten, um gleichzeitige Anfragen innerhalb einer Funktions-Instance zu verarbeiten. Wenn der Gremlin-Treiber, den Sie verwenden, über einen Verbindungspool verfügt, konfigurieren Sie ihn so, dass er nur eine Verbindung verwendet.

Verwenden Sie bei jeder Abfrage eine Wiederholungslogik, um mit Verbindungsfehlern umzugehen. Obwohl das Ziel darin besteht, eine einzige Verbindung für die gesamte Lebensdauer eines Ausführungskontextes aufrechtzuerhalten, können unerwartete Netzwerkereignisse dazu führen, dass diese Verbindung abrupt beendet wird. Solche Verbindungsfehler äußern sich je nach verwendetem Treiber als unterschiedliche Fehler. Sie sollten Ihre Lambda-Funktion so programmieren, dass sie diese Verbindungsprobleme behebt und bei Bedarf versucht, die Verbindung wiederherzustellen.

Einige Gremlin-Treiber kümmern sich automatisch um erneute Verbindungen. Der Java-Treiber versucht beispielsweise automatisch, die Konnektivität zu Neptune für Ihren Client-Code wiederherzustellen. Mit diesem Treiber muss Ihr Funktionscode nur zurückgezogen werden und die Abfrage erneut versuchen. Die Python-Treiber JavaScript und die Python-Treiber implementieren dagegen keine automatische Wiederverbindungslogik. Daher muss Ihr Funktionscode bei diesen Treibern versuchen, die Verbindung nach dem Zurückziehen erneut herzustellen, und die Abfrage erst wiederholen, wenn die Verbindung wieder hergestellt wurde.

Die Codebeispiele hier beinhalten Logik zur Wiederherstellung einer Verbindung, anstatt davon auszugehen, dass der Client dies übernimmt.

Empfehlungen für die Verwendung von Gremlin-Schreibanforderungen in Lambda

Wenn Ihre Lambda-Funktion Grafikdaten ändert, sollten Sie eine back-off-and-retry Strategie zur Behandlung der folgenden Ausnahmen in Betracht ziehen:

  • ConcurrentModificationException – Die Neptune-Transaktionssemantik bedeutet, dass Schreibanforderungen manchmal mit einer ConcurrentModificationException fehlschlagen. Versuchen Sie es in diesen Situationen mit einem exponentiellen back-off-based Wiederholungsmechanismus.

  • ReadOnlyViolationException – Da sich die Cluster-Topologie aufgrund von geplanten oder ungeplanten Ereignissen jederzeit ändern kann, können Schreibzuständigkeiten von einer Instance im Cluster auf eine andere übertragen werden. Wenn Ihr Funktionscode versucht, eine Schreibanforderung an eine Instance zu senden, die nicht mehr die primäre (Writer-)Instance ist, schlägt die Anforderung mit einer ReadOnlyViolationException fehl. Schließen Sie in diesem Fall die bestehende Verbindung, stellen Sie erneut eine Verbindung zum Cluster-Endpunkt her und wiederholen Sie dann die Anforderung.

Wenn Sie eine back-off-and-retry Strategie zur Behandlung von Problemen mit Schreibanforderungen verwenden, sollten Sie außerdem erwägen, idempotente Abfragen für Erstellungs- und Aktualisierungsanforderungen zu implementieren (z. B. mit fold () .coalesce () .unfold ().

Empfehlungen für die Verwendung von Gremlin-Leseanforderungen in Lambda

Wenn Sie eine oder mehrere Lesereplikate in Ihrem Cluster haben, ist es sinnvoll, die Leseanforderungen auf diese zu verteilen. Eine Möglichkeit besteht darin, den Reader-Endpunkt zu verwenden. Der Reader-Endpunkt gleicht Verbindungen zwischen den Replikaten aus, auch wenn sich die Cluster-Topologie ändert, wenn Sie Replikate hinzufügen oder entfernen oder ein Replikat zur neuen primären Instance heraufstufen.

Die Verwendung des Reader-Endpunkts kann jedoch unter bestimmten Umständen zu einer ungleichmäßigen Nutzung der Cluster-Ressourcen führen. Der Reader-Endpunkt funktioniert, indem er regelmäßig den Host ändert, auf den der Eintrag verweist. DNS Wenn ein Client viele Verbindungen öffnet, bevor sich der DNS Eintrag ändert, werden alle Verbindungsanfragen an eine einzelne Neptune-Instanz gesendet. Dies kann bei einem Lambda-Szenario mit hohem Durchsatz der Fall sein, in dem eine große Anzahl gleichzeitiger Anfragen an Ihre Lambda-Funktion dazu führt, dass mehrere Ausführungskontexte mit jeweils eigener Verbindung erstellt werden. Wenn diese Verbindungen fast gleichzeitig erstellt werden, verweisen sie wahrscheinlich alle auf dasselbe Replikat im Cluster und tun dies so lange, bis die Ausführungskontexte wiederverwendet werden.

Eine Möglichkeit, Anfragen auf Instances zu verteilen, besteht darin, Ihre Lambda-Funktion so zu konfigurieren, dass sie eine Verbindung mit einem Instance-Endpunkt herstellt, der nach dem Zufallsprinzip aus einer Liste von Replikat-Instance-Endpunkten ausgewählt wird, und nicht mit dem Reader-Endpunkt. Der Nachteil dieser Vorgehensweise besteht darin, dass der Lambda-Code Änderungen in der Cluster-Topologie verarbeiten muss, indem er den Cluster überwacht und die Endpunktliste aktualisiert, wenn sich die Mitgliedschaft des Clusters ändert.

Wenn Sie eine Java-Lambda-Funktion schreiben, die Leseanforderungen zwischen Instances in Ihrem Cluster ausgleichen muss, können Sie den Gremlin-Client für Amazon Neptune verwenden, einen Java-Gremlin-Client, der Ihre Cluster-Topologie kennt und Verbindungen und Anfragen in fairer Weise auf eine Reihe von Instances in einem Neptune-Cluster verteilt. Dieser Blog-Beitrag enthält ein Beispiel für eine Java-Lambda-Funktion, die den Gremlin-Client für Amazon Neptune verwendet.

Faktoren, die den Kaltstart der Neptune-Gremlin-Lambda-Funktionen verlangsamen können

Das erste Mal, dass eine AWS Lambda Funktion aufgerufen wird, wird als Kaltstart bezeichnet. Es gibt mehrere Faktoren, die die Latenz eines Kaltstarts erhöhen können:

  • Stellen Sie sicher, dass Sie Ihrer Lambda-Funktion ausreichend Speicherplatz zuweisen.   — Die Kompilierung während eines Kaltstarts kann für eine Lambda-Funktion erheblich langsamer sein als bei eingeschalteter Funktion, EC2 da AWS Lambda CPU Zyklen linear proportional zum Speicher zugewiesen werden, den Sie der Funktion zuweisen. Bei 1.769 MB Arbeitsspeicher erhält eine Funktion das Äquivalent eines vollen V CPU (eine CPU V-Sekunde an Credits pro Sekunde). Die Auswirkung, wenn nicht genügend Speicher für den Empfang ausreichender CPU Zyklen zugewiesen wird, ist bei großen Lambda-Funktionen, die in Java geschrieben wurden, besonders ausgeprägt.

  • Beachten Sie, dass die Aktivierung der IAM Datenbankauthentifizierung einen Kaltstart verlangsamen kann — AWS Identity and Access Management (IAM) Datenbankauthentifizierung kann auch Kaltstarts verlangsamen, insbesondere wenn die Lambda-Funktion einen neuen Signaturschlüssel generieren muss. Diese Latenz wirkt sich nur auf den Kaltstart und nicht auf nachfolgende Anfragen aus, denn sobald die IAM DB-Authentifizierung die Verbindungsdaten eingerichtet hat, überprüft Neptune nur regelmäßig, ob sie noch gültig sind.