API REST sin servidor "en la rodilla en 5 minutos"

Hola Habr! Hoy continuamos la discusión sobre las oportunidades que nos brinda Amazon Web Services y cómo usar estas oportunidades para resolver problemas de aplicaciones.

En un ejemplo simple, consideraremos crear en solo unos minutos nuestra propia API REST autoescalable sin servidor con análisis de casos, obteniendo una lista para un recurso.

Interesante? ¡Entonces ve debajo del corte!


(Fuente)

En lugar de unirse


No utilizaremos ninguna base de datos para analizar el ejemplo; en cambio, nuestra fuente de información será un archivo de texto sin formato en AWS S3.

  • Entonces, suponga que en AWS S3 tenemos un archivo de texto con encabezados y algún proceso escribe información en él.
  • Crearemos una API en la nube que devolverá una respuesta JSON como una solicitud GET con el parámetro pasado.
  • Al mismo tiempo, dependiendo de la complejidad de las tareas y, como consecuencia, de los mayores requisitos para el poder de procesamiento de los recursos, no tiene que preocuparse por ello, porque El servicio es totalmente autoescalable. Y esto significa que no necesita ninguna administración, asignación y administración del servidor, solo cargue su código y ejecútelo.

Arquitectura del sistema en desarrollo.




Componentes de Amazon Web Services utilizados:

  • Amazon S3 : almacenamiento de objetos, que le permite almacenar cantidades casi ilimitadas de información;
  • AWS Identity and Access Management (IAM) : un servicio que proporciona la capacidad de controlar de forma segura el acceso a los servicios y recursos de AWS. Con IAM, puede crear, administrar, administrar usuarios y grupos de AWS, y usar permisos para otorgar o denegar el acceso a los recursos de AWS;
  • AWS Lambda es un servicio que le permite ejecutar código sin realizar copias de seguridad y configurar servidores. Toda la potencia informática se escala automáticamente para cada llamada. La tarifa se cobra en función de la cantidad de solicitudes de funciones y su duración, es decir, tiempo durante el cual se ejecuta el código.
    El nivel de acceso gratuito (nivel gratuito) implica 1 millón de solicitudes por mes gratis y 400K Gb-s. Lenguajes admitidos: Node.js, Java, C #, Go, Python, Ruby, PowerShell
    . Utilizaremos Python:

    • La biblioteca boto3 es un AWS SDK para Python que le permite interactuar con varios servicios de Amazon;
  • Amazon API Gateway es un servicio de desarrollador totalmente administrado diseñado para crear, publicar, mantener, monitorear y proteger API a cualquier escala. Además de la capacidad de usar múltiples versiones de la misma API (etapas) para la depuración, el refinamiento y las pruebas, el servicio le permite crear API REST sin servidor utilizando AWS Lambda. Lambda ejecuta código en una infraestructura informática altamente accesible, eliminando la necesidad de distribución, escalado y administración del servidor.
    El nivel gratuito para HTTP / REST API incluye un millón de llamadas API por mes durante 12 meses

Preparación de datos


Se usará un archivo de texto con una pestaña como delimitador de campo como fuente de información para generar respuestas a una solicitud GET REST. La información ahora realmente no importa para este ejemplo, pero para un mayor uso de la API, descargué del terminal de operaciones de Quik una tabla de operaciones actuales en bonos denominados en rublos rusos, la guardé en bond.txt y coloqué este archivo en un bucket AWS S3 especialmente creado.

Un ejemplo de la información recibida es como se muestra en la siguiente figura:



A continuación, debe escribir una función que lea la información del archivo bond.txt, analizarla y emitirla a pedido. AWS Lambda funcionará bien con esto. Pero primero, deberá crear una nueva función que permita que la función Lambda creada lea la información del bucket ubicado en AWS S3.

Crear roles para AWS Lambda


  1. En la consola de administración de AWS, vaya al servicio AWS IAM y luego a la pestaña "Roles", haga clic en el botón "Crear rol";

    Agregar un nuevo rol

  2. AWS Lambda utilizará el rol que estamos creando ahora para leer información de AWS S3. Por lo tanto, en el siguiente paso, seleccione "Seleccionar tipo de confianza" -> "Servicio Aws" y "Elija el servicio que utilizará esta función" -> "Lambda" y haga clic en el botón "Siguiente: Permisos"

    Rol de servicio Lambda

  3. Ahora debe establecer las políticas de acceso para los recursos de AWS que se utilizarán en el rol recién creado. Porque la lista de políticas es bastante impresionante, al usar el filtro para políticas, le indicamos "S3". Como resultado, obtenemos una lista filtrada para el servicio S3. Tenga en cuenta la casilla de verificación frente a la política "AmazonS3ReadOnlyAccess" y haga clic en el botón "Siguiente: Etiquetas".

    Políticas de roles

  4. El paso (Agregar etiquetas (opcional)) es opcional, pero puede especificar etiquetas para Roles si lo desea. No haremos esto y pasaremos al siguiente paso: Vista previa. Aquí debe establecer el nombre del rol: "ForLambdaS3-ReadOnly", agregar una descripción y hacer clic en el botón "Crear rol".

    Roles de título


Todo, el rol ha sido creado y podemos usarlo en futuros trabajos.

Cree una nueva función en AWS Lambda


  1. Vaya al servicio AWS Lambda y haga clic en el botón "Crear función":

    Creación de funciones


    Complete todos los campos como se muestra en la captura de pantalla a continuación:

    • Nombre: "getAllBondsList";
    • Tiempo de ejecución - "Python 3.6"
    • Rol: "Elegir un rol existente"
    • Rol existente: aquí seleccionamos el rol que creamos anteriormente: ForLambdaS3-ReadOnly

    Nombre y elección del rol.

  2. Solo queda escribir el código de función y verificar su rendimiento en varias ejecuciones de prueba. Cabe señalar que el componente principal de cualquier función Lambda (si usa Python) es la biblioteca boto3:

    import boto3 s3 = boto3.resource('s3') bucket = s3.Bucket('your-s3-bucket') obj = bucket.Object(key = 'bonds.txt') response = obj.get() 

    La idea básica de nuestra función Python es la siguiente:

    • Abra el archivo bond.txt;
    • Leer encabezados de columna;
    • Romper registros por página (10 colecciones en nuestro caso);
    • Seleccione la página deseada;
    • Mapear el nombre de las columnas y registros;
    • Dar el resultado en forma de colecciones.

    No dedicaremos mucho tiempo al código de función en sí mismo y a la implementación técnica, todo es bastante simple aquí y el código completo está disponible en mi GitHub .

      for i in range(0, len(lines_proc)): d = dict((u''.join(key), u''.join(value)) for (key, value) in zip(headers, lines_proc[i].split("\t"))) response_body.append(d) return { 'statusCode': 200, 'page' : num_page, 'body': response_body } 

    Inserte el código (o escriba el suyo :)) en el bloque "Código de función" y haga clic en el botón "Guardar" en la esquina superior derecha de la pantalla.

    Inserción de código

  3. Crea eventos de prueba. Después de insertar el código, la función está disponible para iniciar y probar. Haga clic en el botón "Prueba" y cree algunos eventos de prueba: iniciar la función lambda_handler con diferentes parámetros. A saber:

    • Inicio de una función con el parámetro 'página': '100';
    • Lanzar una función con el parámetro 'página': '1000000';
    • Inicio de una función con el parámetro 'página': 'bla-bla-bla';
    • Ejecutar una función sin el parámetro 'página'.

    Evento de prueba Página100


    Comenzando la función creada con el envío de la página del evento de prueba == 100. Como se puede ver en la captura de pantalla a continuación, la función funcionó correctamente, devolvió el estado 200 (OK), así como una colección de colecciones que corresponden a la centésima página de datos divididos usando paginación.

    Evento de prueba de activación Página100


    Para la pureza del experimento, lanzaremos otro evento de prueba: "PageBlaBlaBla". En este caso, la función devuelve el resultado con el código 415 y un comentario de que es necesario verificar la corrección de los parámetros pasados:

    Evento de prueba PageBlaBlaBla


    Desencadenante de evento PageBlaBlaBla



Creación de API


Después de que todos los otros casos se prueban y se comprende que la función Lambda funciona como esperamos, procedemos a crear la API. Creemos un punto de acceso a la función Lambda creada anteriormente y, además, configuremos la protección contra inicios no deseados utilizando la clave API.

  • Vaya al servicio AWS API Gateway. Haga clic en el botón Crear API, establezca el nombre de la API - getAllBondsList

    Crea una nueva API

  • Agregue el método GET a la API recién creada. Para hacer esto, seleccione Acciones -> Crear método, seleccione el método GET en la lista desplegable y haga clic en la marca de verificación

    Nuevo método GET


    A continuación, indicamos que el método GET utilizará nuestra función lambda getAllBondsList. Selecciónelo y haga clic en el botón Guardar.

    Enlace de función Lambda

  • Implementemos nuestra API, obteniendo así la URL para llamar a la API.
    Haga clic en Acciones -> Implementar API, y luego, Etapa de implementación -> Nueva etapa
    Es posible implementar la API en diferentes etapas y puede llamar a estas etapas a su gusto (por ejemplo, DEV / QA / PROD). Implementaremos de inmediato a PROD.
    Implementar API


    Después de la implementación, estará disponible un enlace para iniciar la API recién creada. Iremos a esta URL en la barra de direcciones del navegador (o ejecutaremos el comando curl en la terminal). Recibiremos una llamada a la API y, como resultado, iniciaremos la función Lambda:

    URL de API


    Usaré la aplicación Postman para demostrar la AWS API Gateway. En él, puede depurar y probar con bastante comodidad el funcionamiento de la API.

    Primeras pruebas de API
    Copie la URL de la etapa PROD a Postman y envíe una solicitud GET a nuestra API:



    Algo parece haber salido mal ... la solicitud GET devolvió una respuesta JSON con el código 400 y una pista de que el parámetro Page no estaba configurado en la solicitud de llamada API. Agregue soporte para los parámetros de solicitud a la API.
  • Soporte para parámetros pasados ​​en la solicitud.
    Volvemos a la configuración de la solicitud GET y vamos al paso Solicitud de método.

    Solicitud de método


    En la configuración detallada de la Solicitud de método, es necesario expandir el bloque Parámetros de cadena de consulta de URL y agregar un nuevo parámetro de "página" y hacer que sea obligatorio:

    Agregar un parámetro


    Regresamos a la página de Ejecución del Método y vamos a la Solicitud de Integración. Bajamos al final de la página y abrimos el bloque "Plantillas de mapeo". Seleccione "Cuando no hay plantillas definidas (recomendado)", en el campo Tipo de contenido, especifique application / json y haga clic en la marca de verificación. Desplazamos hacia abajo la página a continuación e ingresamos el código en el cuadro de texto, como se indica en la imagen a continuación. Después de eso, haga clic en el botón Guardar.

    Solicitud de método


    Habiendo realizado previamente la implementación de la API, verificamos nuevamente, pero con el parámetro "page" pasado:



    Es un exito! ¡Ahora la solicitud funcionó con éxito y nos devolvió las colecciones contenidas en la décima página! ¡Hurra!
  • Solo queda para proteger nuestra API de ataques no deseados desde el exterior.

    Para hacer esto, debe configurar la API de tal manera que al acceder requiera una clave secreta, que se pasa al encabezado.

    Vaya a las claves API y cree un nuevo grupo de claves API: KeyForBondsList.

    Claves API


    Después de que la clave API se haya creado correctamente, debe especificar que la API getAllBondsList debe requerir que la clave API se pase en el encabezado de la solicitud. Y vincule un KeyForBondsList específico a la API getAllBondsList.

    Volvamos a la configuración de la solicitud GET en Solicitud de método y cambie el parámetro API Key Required de falso a verdadero. Ahora la API requerirá la transferencia de la clave API.

    Clave API requerida


    Vaya a Plan de uso y cree un nuevo plan para usar la API.

    En primer lugar, le damos un nombre y una descripción, y en segundo lugar, aquí puede establecer límites para iniciar la API, por ejemplo, no más de un lanzamiento por segundo, etc.

    Crear plan de uso


    Haga clic en Siguiente y vaya a la página siguiente donde necesita conectar las etapas de la API con el plan de uso:

    Vinculando una etapa a un plan de uso


    En la página siguiente, vinculamos las claves de API al plan para usar la API. Haga clic en el botón Agregar claves API al plan de uso y busque las claves API creadas en los pasos anteriores por nombre:

    Enlace de claves API al plan de uso


    Después de realizar la implementación y ejecutar la llamada GET de nuestra API nuevamente, obtenemos la respuesta: "Prohibido", porque al encabezado de la solicitud le falta la clave API:



    Intentemos agregarlo copiando desde las claves API -> KeyForBondsList -> clave API -> Mostrar y pegarlo en la sección correspondiente de la solicitud con la clave "x-api-key":



    ¡Todo salió bien! Esta vez, la solicitud devuelve datos sin ningún problema, la llamada API está segura y protegida de intrusos por la clave secreta API.

Conclusiones y resumen


En este artículo, analizamos la creación de una API REST autoescalable sin servidor utilizando los servicios en la nube de Amazon. El artículo no era el más pequeño en volumen, pero traté de explicar lo más posible todo el proceso de creación de la API y componer toda la secuencia de acciones.

Estoy seguro de que después de una o dos repeticiones de los pasos descritos en el artículo, puede aumentar sus API en la nube en 5 minutos o incluso más rápido.

Debido a su relativa simplicidad, bajo costo y potencia, el servicio AWS API Gateway abre amplias oportunidades para que los desarrolladores lo utilicen en el trabajo y en proyectos comerciales. Para consolidar el material teórico en este artículo, intente suscribirse a una suscripción anual gratuita de Amazon Web Services y siga los pasos anteriores para crear una API REST.

Para cualquier pregunta y sugerencia, estoy listo para hablar con gusto. ¡Espero sus comentarios sobre el artículo y les deseo éxito!

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


All Articles