Serverloses PHP unter AWS Lambda

Hallo an alle. Am Montag findet die erste Lektion in der neuen Gruppe des Kurses "Backend PHP Developer" statt . In diesem Zusammenhang veröffentlichen wir weiterhin nützliches Material zu diesem Thema. Fangen wir an.



Wie Simon Wordley glaube ich, dass Serverless Computing ein äußerst interessanter Bereich ist, vor allem aufgrund des detaillierten Zahlungssystems (zahlen Sie nur, wenn Ihr Code ausgeführt wird), und Sie müssen sich nicht um die Wartung und Vorbereitung von Servern und Containern kümmern. So sehr, dass ich mit der offenen PHP-Laufzeit für Apache OpenWhisk arbeite , von der eine kommerzielle Version als eine der Funktionen der IBM Cloud verfügbar ist.

Es gibt andere Anbieter ohne Server, und AWS Lambda ist Marktführer, aber bis vor kurzem war die PHP-Unterstützung äußerst umständlich und unprätentiös. Dies änderte sich Ende 2018 mit der neuen Lambda- Laufzeit-API und Layer-Unterstützung .

Werfen wir einen Blick auf die praktischen Aspekte von serverlosem PHP auf Lambda mit dem Serverless Framework .

TL; DR


Der Quellcode für eine einfache Hello World befindet sich in meinem Lambda-PHP- Repository auf Github. Gehen Sie zum Abschnitt Notizen und wir können fortfahren.

PHP Laufzeit


Mit der Laufzeit-API können Sie jede Laufzeit mit Lambda verwenden. In gewisser Weise ähnelt dies OpenWhisk, da zwischen der serverlosen Plattform und der Laufzeit eine HTTP-API besteht. Es gibt einen großen Unterschied, dass bei Lambda die Laufzeit eine Anforderung an die Plattform sendet, um die Anrufdaten zu empfangen, während OpenWhisk den Endpunkt aufruft, den die Laufzeit bereitstellen soll. Weitere Informationen finden Sie in Michael Moussas AWS-Blogbeitrag , der mich zu dieser Aufgabe inspiriert hat.

Um loszulegen, benötigen wir die PHP-Laufzeit für Lambda. Es besteht aus einer ausführbaren PHP-Datei, PHP-Code zum Aufrufen einer serverlosen Funktion und einer bootstrap Datei, wie von der Plattform gefordert. Aus diesen drei Dingen sammeln wir eine Schicht. Ebenen können in verschiedenen Konten wiederverwendet werden. Daher bin ich überrascht, dass AWS uns kein PHP-Konto zur Verfügung stellt. Unglaublich, aber wahr, sie verwenden kein PHP 7.3, also müssen wir unser eigenes erstellen.
Alle Dateien, die wir in unserem Projekt in das Verzeichnis layer/php gestellt haben.

Erstellen einer ausführbaren PHP-Datei


Wir benötigen eine ausführbare PHP-Datei, die in Lambda-Containern ausgeführt wird. Der einfachste Weg, dies zu tun, besteht darin, es auf derselben Plattform wie Lambda zu kompilieren, sodass wir EC2 verwenden werden. In Michaels Artikel wird erklärt, wie das geht. Ich habe diese Befehle in das Skript compile_php.sh eingeschlossen und sie dann auf eine EC2-Instanz kopiert, ausgeführt und die ausführbare Datei zurück auf meinen Computer kopiert:

 $ export AWS_IP=ec2-user@{ipaddress} $ export SSH_KEY_FILE=~/.ssh/aws-key.rsa $ scp -i $SSH_KEY_FILE compile_php.sh $AWS_IP:doc/compile_php.sh $ ssh -i $SSH_KEY_FILE -t $AWS_IP "chmod a+x compile_php.sh && ./compile_php.sh 7.3.0" $ scp -i $SSH_KEY_FILE $AWS_IP:php-7-bin/bin/php layer/php/php 


Dieser Ansatz macht es gut reproduzierbar und hoffentlich wird es nur auf neue Versionen von PHP aktualisiert.

Bootstrapping


Da wir die Laufzeit-API verwenden, benötigen wir eine bootstrap Datei. Lambda selbst benötigt einen solchen Namen, um die Datei anzugeben, und reagiert auf einen Funktionsaufruf, der mit den Bildern übereinstimmt, indem die API in einer Schleife aufgerufen wird.

Im Wesentlichen müssen wir uns in einer Schleife befinden und den Endpunkt /next aufrufen, um zu verstehen, was als nächstes aufgerufen werden soll, ihn aufrufen und dann die Antwort an den Endpunkt /response senden.
AWS bietet ein Beispiel in BASH mit Curl :

 while true do HEADERS="$(mktemp)" # Get an event EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Execute the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done 


Wir wollen dasselbe in PHP tun, und obwohl ich es selbst schreiben könnte, ist Pariksit Agnihotri in PHP-Lambda-Runtime / runtime.php bereits vor mir, also kopieren wir dies einfach in layer/php/runtime.php . In meiner Version habe ich mehrere Änderungen vorgenommen, json_encoding hinzugefügt und den Fehlerbehandler verbessert.
Die layer/php/bootstrap sehr einfach und alles, was dazu erforderlich ist, ist die Ausführung der ausführbaren PHP-Datei mit dieser Datei:

 #!/bin/sh cd $LAMBDA_TASK_ROOT /opt/php /opt/runtime.php 


Das ist alles. Jetzt haben wir drei Dateien in Layer / PHP:

  • php - php ausführbare Datei;
  • runtime.php - Laufzeit-API-Arbeitsdatei;
  • bootstrap ist die erforderliche Lambda-Datei.


Infolgedessen wird all dies zu einer PHP-Schicht (Schicht) in unserer Lambda-Anwendung.

Konfigurieren Sie Serverless Framework


Das Serverless Framework bietet eine wiederholbare Konfiguration und Bereitstellung einer serverlosen Anwendung. Ich bin ein Fan dieses Konzepts und möchte mehr solcher Tools verwenden. Wir werden das Serverless Framework für unsere PHP Hello World verwenden.
Da es im Serverless Framework keine praktische Vorlage für Anwendungen in PHP gibt, erstellen wir einfach die Datei serverless.yml im Verzeichnis mit unserem Projekt.
Für den Anfang das Grundlegendste:

 service: php-hello-world provider: name: aws runtime: provided region: eu-west-2 memorySize: 128 


Wir werden unsere Anwendung php-hello-world aufrufen und AWS als Anbieter verwenden. Seit ich in Großbritannien bin, habe ich die Region London gegründet . Wir brauchen nicht viel Speicher, also reichen 128 MB aus.
Laufzeit ist normalerweise die Sprache, in der Ihre Funktion ausgeführt werden soll. Um die runtime API , die unsere bootstrap Datei ausführen wird, setzen Sie dieses Feld auf " Bereitgestellt" .
Und Sie benötigen eine .gitignore Datei, die .gitignore enthält:

 .serverless 


Da in git brauchen wir dieses Verzeichnis nicht.
Als nächstes fügen wir unsere Ebene zu serverless.yml hinzu, indem wir serverless.yml hinzufügen:

 layers: php: path: layer/php 


Dadurch wird eine AWS-Ebene erstellt und ihr der Name PhpLambdaLayer , auf den wir in unserer Funktion verweisen können.

Schreiben wir die Hello World Funktion
Jetzt können wir unsere serverlose PHP-Funktion schreiben. Dies muss in die Datei handler.php werden:

 <?php function hello($eventData) : array { return ["msg" => "hello from PHP " . PHP_VERSION]; } 


Die Funktion nimmt Informationen über das Ereignis entgegen und gibt ein assoziatives Array zurück.
Um das Serverless Framework über die Bereitstellung unserer Funktion zu informieren, müssen Sie der Datei serverless.yml Folgendes hinzufügen:

 functions: hello: handler: handler.hello layers: - {Ref: PhpLambdaLayer} 


Serverless Framework unterstützt mehrere Funktionen für eine Anwendung. Jeder von ihnen hat einen Namen, in diesem Fall hello , und in unserem Fall einen Handler, bei dem es sich um einen Dateinamen ohne Erweiterung handelt, gefolgt von einem Punkt und dem Funktionsnamen in dieser Datei. Daher bedeutet der Handler handler.hello , dass wir die Funktion hello() in handler.php .
Schließlich melden wir auch Funktionen an unsere PHP-Schicht, damit diese PHP-Code ausführen kann.

Einsatz in Lambda


Um unsere Funktion mit ihrer Ebene zu erweitern, führen wir den folgenden Befehl aus:

 $ sls deploy 


Wenn der Befehl so lange wie möglich ausgeführt wird, wird eine ähnliche Ausgabe erhalten:



Erfüllung unserer Funktion


Nach der Bereitstellung können wir die Funktion mit dem folgenden Befehl aufrufen:

 $ sls invoke -f hello -l 




Und du bist fertig!

Zusammenfassend


Mit neuen Ebenen und Laufzeit-APIs können Sie jetzt problemlos PHP-Funktionen ohne Server in Lambda ausführen. Dies sind gute Nachrichten für PHP-Entwickler, die an AWS gebunden sind.

Warten auf Ihre Kommentare, Freunde!

Source: https://habr.com/ru/post/de453116/


All Articles