PHP sans serveur sur AWS Lambda

Bonjour à tous. Lundi, la première leçon aura lieu dans le nouveau groupe du cours "Backend PHP Developer" . À cet égard, nous continuons de publier des documents utiles sur le sujet. Commençons.



Comme Simon Wordley , je pense que l'informatique sans serveur est un domaine extrêmement intéressant, principalement en raison du système de paiement granulaire (ne payez que lorsque votre code est exécuté), et vous n'avez pas à vous soucier de l'entretien et de la préparation des serveurs et des conteneurs. À tel point que je travaille avec le PHP Runtime ouvert pour Apache OpenWhisk , dont une version commerciale est disponible comme l'une des fonctionnalités du cloud IBM .

Il existe d'autres fournisseurs sans serveur et AWS Lambda est un leader du marché, mais jusqu'à récemment, la prise en charge de PHP était extrêmement lourde et sans prétention. Cela a changé fin 2018 avec la nouvelle API d'exécution Lambda et la prise en charge des couches .

Jetons un coup d'œil aux aspects pratiques du PHP sans serveur sur Lambda avec le Framework sans serveur .

TL; DR


Le code source d'un simple Hello World se trouve dans mon dépôt lambda-php sur Github. Allez à la section Notes et nous pouvons continuer.

Runtime PHP


L'API d'exécution vous permet d'utiliser n'importe quel environnement d'exécution avec Lambda. D'une certaine manière, cela est similaire à OpenWhisk, car il existe une API HTTP entre la plate-forme sans serveur et le runtime. Il y a une grande différence avec Lambda, le runtime envoie une demande à la plateforme pour recevoir les données d'appel, tandis qu'OpenWhisk appelle le point de terminaison que le runtime doit fournir. Pour plus d'informations, consultez le billet de blog AWS de Michael Moussa qui m'a inspiré pour faire le travail.

Pour commencer, nous avons besoin du runtime PHP pour Lambda. Il consistera en un exécutable PHP, du code PHP pour appeler une fonction sans serveur et un fichier d' bootstrap , comme requis par la plateforme. De ces trois choses, nous collectons une couche. Les couches peuvent être réutilisées dans différents comptes, je suis donc surpris qu'AWS ne nous fournisse pas de compte PHP. Incroyable, mais c'est vrai, ils n'utilisent pas PHP 7.3, nous devrons donc construire le nôtre.
Tous les fichiers que nous mettons dans le répertoire layer/php de notre projet.

Construire un exécutable PHP


Nous avons besoin d'un exécutable PHP qui s'exécutera à l'intérieur des conteneurs Lambda. La façon la plus simple de le faire est de le compiler sur la même plate-forme que Lambda, nous allons donc utiliser EC2. L'article de Michael explique comment procéder, et j'ai encapsulé ces commandes dans le script compile_php.sh , puis pour le copier dans une instance EC2, exécuter et copier le fichier exécutable sur mon ordinateur:

 $ 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 


Cette approche le rendra bien reproductible et, espérons-le, ne fera que passer à de nouvelles versions de PHP.

Bootstrapping


Puisque nous utilisons l'API d'exécution, nous avons besoin d'un fichier d' bootstrap . Lambda lui-même requiert un tel nom pour spécifier le fichier; il répond à un appel de fonction qui correspond aux images en appelant l'API dans une boucle.

En substance, nous devons être en boucle et appeler le point de terminaison /next pour comprendre quoi appeler ensuite, l'appeler, puis envoyer la réponse au point de terminaison /response .
AWS fournit un exemple dans BASH utilisant 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 


Nous voulons faire de même en PHP, et bien que je puisse l'écrire moi-même, Pariksit Agnihotri est déjà en avance sur moi dans PHP-Lambda-Runtime / runtime.php , donc nous le copions simplement dans layer/php/runtime.php . Dans ma version, j'ai apporté plusieurs modifications, ajouté json_encoding et amélioré le gestionnaire d'erreurs.
La layer/php/bootstrap fichier layer/php/bootstrap très simple, et tout ce qui est requis est d'exécuter l'exécutable PHP avec ce fichier:

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


C’est tout. Nous avons maintenant trois fichiers en couche / php:

  • php - Fichier exécutable php ;
  • runtime.php - fichier de travail de l'API d'exécution;
  • bootstrap est le fichier Lambda requis.


En conséquence, tout cela deviendra une couche PHP (couche) dans notre application Lambda.

Configurer l'infrastructure sans serveur


Le Framework sans serveur fournit une configuration et un déploiement reproductibles d'une application sans serveur. Je suis fan de ce concept et je souhaite utiliser davantage de tels outils. Nous utiliserons le Framework Serverless pour notre PHP Hello World.
Puisqu'il n'y a pas de modèle pratique pour les applications en PHP dans le Framework sans serveur, nous créons simplement le fichier serverless.yml dans le répertoire avec notre projet.
Pour commencer, le plus basique:

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


Nous appellerons notre application php-hello-world et utiliserons AWS comme fournisseur. Depuis que je suis au Royaume-Uni, j'ai établi la région de Londres . Nous n'avons pas besoin de beaucoup de mémoire, donc 128 Mo suffiront.
Le runtime est généralement le langage dans lequel vous souhaitez que votre fonction s'exécute. Pour utiliser l' runtime API que notre fichier d' bootstrap exécutera, vous définissez ce champ sur fourni .
Et vous aurez besoin d'un fichier .gitignore contenant:

 .serverless 


Puisque dans git nous n'avons pas besoin de ce répertoire.
Ensuite, ajoutons notre couche à serverless.yml en ajoutant:

 layers: php: path: layer/php 


Cela créera une couche AWS et lui donnera le nom PhpLambdaLayer , que nous pouvons référencer dans notre fonction.

Écrivons la fonction Hello World
Nous pouvons maintenant écrire notre fonction PHP sans serveur. Celui-ci doit être saisi dans le fichier handler.php :

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


La fonction prend des informations sur l'événement et renvoie un tableau associatif.
Pour informer le Serverless Framework du déploiement de notre fonction, vous devez ajouter ce qui suit au fichier serverless.yml :

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


Serverless Framework prend en charge plusieurs fonctions pour une seule application. Chacun d'eux a un nom, dans ce cas hello , et, dans notre cas, un gestionnaire, qui est un nom de fichier sans extension, suivi d'un point, puis du nom de la fonction dans ce fichier. Ainsi, le gestionnaire handler.hello signifie que nous exécuterons la fonction hello() dans handler.php .
Enfin, nous rapportons également des fonctions à notre couche PHP afin qu'elle puisse exécuter du code PHP.

Déploiement dans Lambda


Pour étendre notre fonction avec sa couche, nous exécutons la commande suivante:

 $ sls deploy 


Si la commande est exécutée aussi longtemps que possible, une sortie similaire à celle-ci sera obtenue:



Accomplissement de notre fonction


Après le déploiement, nous pouvons appeler la fonction à l'aide de la commande:

 $ sls invoke -f hello -l 




Et vous avez terminé!

Pour résumer


Avec de nouvelles couches et API d'exécution, vous pouvez désormais exécuter facilement des fonctions sans serveur PHP dans Lambda. C'est une bonne nouvelle pour les développeurs PHP liés à AWS.

En attente de vos commentaires, amis!

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


All Articles