PHP sin servidor en AWS Lambda

Hola a todos El lunes, la primera lección se llevará a cabo en el nuevo grupo del curso Backend PHP Developer . En este sentido, continuamos publicando material útil sobre el tema. Empecemos



Al igual que Simon Wordley , creo que la informática sin servidor es un área extremadamente interesante, principalmente debido al sistema de pago granular (pague solo cuando se ejecuta su código), y no necesita preocuparse por el servicio y la preparación de servidores y contenedores. Tanto es así que trabajo con el PHP Runtime abierto para Apache OpenWhisk , cuya versión comercial está disponible como una de las características de IBM Cloud .

Hay otros proveedores sin servidor, y AWS Lambda es el líder del mercado, pero hasta hace poco, el soporte de PHP era extremadamente engorroso y sin pretensiones. Esto cambió a finales de 2018 con la nueva API de Lambda runtime y compatibilidad con capas .

Echemos un vistazo a los aspectos prácticos de PHP sin servidor en Lambda con Serverless Framework .

TL; DR


El código fuente de un simple Hello World está en mi repositorio lambda-php en Github. Vaya a la sección de Notas y podemos continuar.

Tiempo de ejecución de php


La API de tiempo de ejecución le permite utilizar cualquier tiempo de ejecución con Lambda. En cierto modo, esto es similar a OpenWhisk, ya que existe una API HTTP entre la plataforma sin servidor y el tiempo de ejecución. Hay una gran diferencia que con Lambda, el tiempo de ejecución envía una solicitud a la plataforma para recibir los datos de la llamada, mientras que OpenWhisk llama al punto final que debe proporcionar el tiempo de ejecución. Para obtener más información, consulte la publicación del blog AWS de Michael Moussa que me inspiró a hacer el trabajo.

Para comenzar, necesitamos el tiempo de ejecución de PHP para Lambda. Consistirá en un ejecutable PHP, un código PHP para llamar a una función sin servidor y un archivo de bootstrap , según lo requiera la plataforma. De estas tres cosas recogemos una capa. Las capas se pueden reutilizar en diferentes cuentas, por lo que me sorprende que AWS no nos proporcione una cuenta PHP. Increíble, pero cierto, no usan PHP 7.3, por lo que tendremos que construir el nuestro.
Todos los archivos que ponemos en el directorio layer/php de nuestro proyecto.

Construyendo un ejecutable PHP


Necesitamos un ejecutable PHP que se ejecute dentro de los contenedores Lambda. La forma más fácil de hacerlo es compilarlo en la misma plataforma que Lambda, por lo que utilizaremos EC2. El artículo de Michael explica cómo hacer esto, y envolví estos comandos en el script compile_php.sh , luego para copiarlo en una instancia de EC2, ejecutar y copiar el archivo ejecutable en mi computadora:

 $ 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 


Este enfoque lo hará bien reproducible y, con suerte, solo se actualizará a nuevas versiones de PHP.

Bootstrapping


Como usamos la API de tiempo de ejecución, necesitamos un archivo de bootstrap . Lambda requiere un nombre para especificar el archivo; responde a una llamada de función que coincide con las imágenes llamando a la API en un bucle.

En esencia, debemos estar en un bucle y llamar al punto final /next para comprender qué llamar a continuación, llamarlo y luego enviar la respuesta al punto final /response .
AWS proporciona un ejemplo en BASH usando 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 


Queremos hacer lo mismo en PHP, y aunque podría escribirlo yo mismo, Pariksit Agnihotri ya está por delante de mí en PHP-Lambda-Runtime / runtime.php , así que simplemente copiamos esto en layer/php/runtime.php . En mi versión, hice varios cambios, agregué json_encoding y mejoré el controlador de errores.
La layer/php/bootstrap archivo layer/php/bootstrap muy simple, y todo lo que se requiere de ella es ejecutar el ejecutable PHP con este archivo:

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


Eso es todo Ahora tenemos tres archivos en capa / php:

  • php : archivo ejecutable de php ;
  • runtime.php - archivo de trabajo de API de tiempo de ejecución;
  • bootstrap es el archivo Lambda requerido.


Como resultado, todo esto se convertirá en una Capa PHP (capa) en nuestra aplicación Lambda.

Configurar el marco sin servidor


Serverless Framework proporciona configuración e implementación repetibles de una aplicación sin servidor. Soy un fanático de este concepto y quiero usar más herramientas de este tipo. Usaremos el Framework Serverless para nuestro PHP Hello World.
Dado que no hay una plantilla conveniente para aplicaciones en PHP en Serverless Framework, simplemente creamos el archivo serverless.yml en el directorio con nuestro proyecto.
Para empezar, lo más básico:

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


Llamaremos a nuestra aplicación php-hello-world y utilizaremos AWS como proveedor. Desde que estoy en el Reino Unido, he establecido la región de Londres . No necesitamos mucha memoria, por lo que 128 MB serán suficientes.
El tiempo de ejecución suele ser el idioma en el que desea que se ejecute su función. Para utilizar la runtime API que ejecutará nuestro archivo bootstrap , establezca este campo como proporcionado .
Y necesitará un archivo .gitignore que contenga:

 .serverless 


Como en git no necesitamos este directorio.
A continuación, agreguemos nuestra capa a serverless.yml agregando:

 layers: php: path: layer/php 


Esto creará una capa de AWS y le dará el nombre de PhpLambdaLayer , al que podemos hacer referencia en nuestra función.

Escribamos la función Hello World
Ahora podemos escribir nuestra función PHP sin servidor. Esto debe ingresarse en el archivo handler.php :

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


La función toma información sobre el evento y devuelve una matriz asociativa.
Para informar a Serverless Framework sobre la implementación de nuestra función, debe agregar lo siguiente al archivo serverless.yml :

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


Serverless Framework admite varias funciones para una aplicación. Cada uno de ellos tiene un nombre, en este caso hello , y, en nuestro caso, un controlador, que es un nombre de archivo sin extensión, seguido de un punto, y luego el nombre de la función en este archivo. Por lo tanto, el controlador handler.hello significa que ejecutaremos la función hello() en handler.php .
Finalmente, también informamos funciones a nuestra capa PHP para que pueda ejecutar código PHP.

Despliegue en Lambda


Para expandir nuestra función con su capa, ejecutamos el siguiente comando:

 $ sls deploy 


Si el comando se ejecuta el mayor tiempo posible, se obtendrá una salida similar a esta:



Cumplimiento de nuestra función.


Después de la implementación, podemos llamar a la función usando el comando:

 $ sls invoke -f hello -l 




Y ya terminaste!

Para resumir


Con nuevas capas y API de tiempo de ejecución, ahora puede ejecutar fácilmente funciones sin servidor PHP en Lambda. Esta es una buena noticia para los desarrolladores de PHP vinculados a AWS.

Esperando sus comentarios, amigos!

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


All Articles