Configurar aplicaciones sin servidor en el entorno de producción

En este capítulo, abordaremos las siguientes recetas:

  • Implementar Azure Functions mediante Ejecutar desde el paquete
  • Implementar Azure Function mediante plantillas de ARM
  • Configurar un dominio personalizado en Azure Functions
  • Técnicas para acceder a la configuración de la aplicación
  • Crear y generar especificaciones de API abierta utilizando Swagger
  • Desglosar grandes API en pequeños subconjuntos de API usando proxies
  • Mover elementos de configuración de un entorno a otro usando recursos

Introducción

Hemos estado hablando sobre las diferentes características de Azure Functions que ayudan a los desarrolladores a compilar rápidamente aplicaciones de back-end. El enfoque de este capítulo se centra en las configuraciones que se deben realizar en un entorno que no sea de desarrollo (como por ejemplo, almacenamiento provisional, UAT y producción).

Implementar Azure Functions mediante Ejecutar desde el paquete

Hemos aprendido diferentes técnicas para desarrollar Azure Functions e implementarla en el cloud.

Como ya sabrás, cada aplicación de función puede tener múltiples funciones alojadas en ella. Todo el contenido relacionado con estas funciones se ubica en la carpeta 

D:\home\site\wwwroot es la ubicación en la que el runtime busca los binarios y todos los archivos de configuración necesarios para ejecutar la aplicación.

En esta receta, veremos una técnica nueva, denominada Ejecutar desde el paquete (anteriormente denominada Ejecutar desde ZIP) para implementar Azure Function como un paquete.

Al utilizar Ejecutar desde el paquete, podemos cambiar la ubicación predeterminada por una cuenta de almacenamiento externo.

Preparación

Necesitamos lo siguiente para completar esta receta:

  1. Visual Studio 2017 debe estar instalado en el equipo de desarrollador local; crear una o más Azure Functions usando Visual Studio. Para este ejemplo, he creado un desencadenador de HTTP y un desencadenador de temporizador:
  • Crea una aplicación de función vacía utilizando el portal de administración de Azure:
  • Una cuenta de almacenamiento: cargaremos el archivo de paquete en la cuenta de almacenamiento.

Cómo hacerlo…

Sigue estos pasos:

  1. Crea un archivo de paquete para la aplicación. Estoy utilizando la misma aplicación que creamos en el capítulo 4, Comprender la experiencia de

desarrollador integrada de Visual Studio Tools.

  • Desplázate a la ubicación en la que se muestra la carpeta bin junto con otros archivos relacionados con tus funciones. Con estos archivos, crea un archivo .zip, que se resalta en la siguiente captura de pantalla:
  • Crea un contenedor de blob (con acceso privado) y carga el archivo de paquete desde el portal o mediante el explorador de Azure Storage.
  • El siguiente paso es generar un token de firma de acceso compartido (SAS) para el contenedor blob para que el runtime de Azure Function tenga los permisos necesarios para acceder a los archivos que se encuentran en el contenedor. Puedes obtener más información sobre SAS en https://docs. microsoft.com/azure/storage/common/storage-dotnet-sharedaccess-signature-part-1:
  • Desplázate hasta Configuración de la aplicación de la aplicación de función que hemos creado y crea una nueva configuración de aplicación con la clave WEBSITE_RUN_FROM_PACKAGE y para que el valor sea la dirección URL de SAS de blob que hemos creado en el paso anterior, como se muestra a continuación. Haz clic en Guardar para guardar los cambios:
  • Eso es todo. Después de realizar la configuración anterior, puedes probar la función:

Cómo funciona…

Si el runtime de Azure Function encuentra una configuración de la aplicación con el nombre WEBSITE_RUN_FROM_PACKAGE, comprende que debe buscar los paquetes en la cuenta de almacenamiento. Entonces, sobre la marcha, el runtime descarga los archivos y los usa para iniciar la aplicación.

Y eso no es todo…

Puedes obtener más información sobre esta técnica y sus ventajas en https:// github.com/Azure/app-service-announcements/issues/84.

Implementar Azure Function mediante plantillas de ARM

Hasta ahora, hemos estado aprovisionando manualmente Azure Functions mediante el portal de administración de Azure.

En esta receta, descubrirás cómo automatizar el proceso de aprovisionamiento de Azure Function utilizando plantillas de Azure Resource Manager (ARM).

Preparación

Antes de comenzar a crear las plantillas de ARM, debemos comprender los otros servicios de Azure de los que depende Azure Function. Los siguientes servicios se crean automáticamente cuando creas una aplicación de función:

Como se muestra en la captura de pantalla anterior, la aplicación de función (en este caso azurefunctioncookbook-gateway) depende de un plan de App Service y una cuenta de almacenamiento:

  • Plan de App Service: puede ser un plan de App Service normal o un plan de consumo.
  • Cuenta de almacenamiento: el runtime de Azure Function usa la cuenta de almacenamiento para registrar información de diagnóstico que podemos utilizar para solucionar problemas.
  • Application Insights: una cuenta opcional de Application Insights. Si no utilizamos Application Insights, tenemos que crear una configuración de aplicación con el nombre AzureWebJobsDashboard en la configuración de aplicación de la función que usa el servicio de tablas de Azure Storage para registrar información de diagnóstico.

Junto con estos servicios, obviamente deberíamos tener un grupo de recursos. En esta receta, supondremos que el grupo de recursos ya existe.

Cómo hacerlo…

A estas alturas, ya sabes que al crear Azure Functions debemos asegurarnos de que también tenemos un plan de App Service y una cuenta de almacenamiento. Empecemos con la creación de la plantilla de ARM usando Visual Studio:

  1. Crea un proyecto nuevo seleccionando Visual C# | Cloud y, a continuación, elige Grupo de recursos de Azure:
  • Al hacer clic en el botón Aceptar  en el paso anterior, se abrirá Seleccionar plantilla de Azure, donde selecciona las plantillas de inicio rápido de Azure (github.com/Azure/azure-quickstart-templates):
  • Busca la palabra function y haz clic en la plantilla 101-function-app-createdynamic para crear la aplicación Azure Function con el plan de consumo:
  • La plantilla JSON necesaria se creará en Visual Studio. Puedes obtener más información sobre el contenido de JSON en https://docs.microsoft.com/ azure/azure-functions/functions-infrastructure-as-code.
  • Implementa el ARM para aprovisionar la aplicación de función y sus recursos dependientes. Puedes implementarlo haciendo clic con el botón derecho en el nombre del proyecto (en mi caso ARMTemplateforFunctionApp), haciendo clic en Implementar y, a continuación, haciendo clic en el botón Nuevo:
  • Selecciona Suscripción, Grupo de recursos y otros parámetros para aprovisionar la aplicación de función. Selecciona todos los campos obligatorios y haz clic en el botón Implementar:
  • Eso es todo. En unos minutos, se iniciará la implementación y se aprovisionarán todos los recursos mencionados en las plantillas de JSON de ARM:

Y eso no es todo…

Estas son algunas de las ventajas de aprovisionar recursos de Azure utilizando plantillas de ARM:

  • Al tener las configuraciones en los archivos JSON, es útil para los desarrolladores insertar los archivos en algún tipo de sistema de control de versiones, como Git o TFS, para que podamos mantener las versiones de los archivos para realizar un seguimiento de todos los cambios.
  • También es posible crear los servicios en diferentes entornos rápidamente.
  • Con las plantillas de ARM, también podemos insertarlos en las canalizaciones de CI/CD para automatizar el aprovisionamiento de entornos adicionales.

Configurar un dominio personalizado en Azure Functions

Por ahora, mirando la dirección URL predeterminada en formato functionappname.

azurewebsites.net de la aplicación Azure Function, es posible que te estés preguntando si es posible tener dominios separados en lugar del dominio predeterminado, ya que tus clientes seguramente tienen sus propios dominios.  Sí, es posible configurar un dominio personalizado para las aplicaciones de función. En esta receta, vamos a aprender a configurarlo.

Preparación

Crear un dominio con cualquiera de los registradores de dominios. También puedes comprar un dominio en el portal mediante el botón Comprar dominio, que está disponible en la hoja Dominios personalizados:

Cuando el dominio esté listo, crea los siguientes registros DNS utilizando un registrador de dominios:

  • Un registro
  • Registro CName

Cómo hacerlo…

Sigue estos pasos:

  1. Ve a la hoja Dominios personalizados de la aplicación Azure Function para la que deseas configurar un dominio:
  • Si has creado un dominio personalizado desde el portal de Azure, se te pedirá que elijas los nombres de host, como se muestra en la hoja Dominio de App Service:
  • Si has elegido ambas opciones, has terminado. Todo el trabajo en la integración de la aplicación de función y el dominio personalizado lo realiza el portal de administración de Azure. Aquí puedes ver la integración de los nombres de host:

Configurar la aplicación de función con un dominio existente

Si ya tienes un dominio personalizado y deseas integrarlo con la aplicación de función, debes crear los siguientes dos registros en el DNS:

  1. Crea un registro A y un registro CNAME en el registrador de dominios. Puedes obtener la dirección IP de la hoja Dominios personalizados:
  • Ve a la hoja Dominios personalizados de la aplicación de función y crea los nombres de host siguientes:

Eso es todo. Has integrado un dominio personalizado con la aplicación Azure Function. Ahora puedes explorar tu aplicación de función usando el nuevo dominio en lugar del predeterminado que Azure te brinda:

Técnicas para acceder a la configuración de la aplicación

En cada aplicación, tendrás al menos algunos elementos de configuración que tal vez no quieras codificar. En su lugar, deseas cambiarlos en el futuro, después de que la aplicación esté activa, sin tocar el código.

En general, clasificaría los elementos de configuración en dos categorías:

  • Algunos de los elementos de configuración pueden ser diferentes en los distintos entornos (por ejemplo, las cadenas de conexión de la base de datos y el servidor SMTP)
  • Algunos de ellos pueden ser iguales en todos los entornos, como algunos números constantes que se utilizan en algunos cálculos del código

Cualquiera que sea el uso del valor de configuración, debes tener un lugar para almacenarlos que sea accesible para tu aplicación.

En esta receta, descubriremos cómo y dónde almacenar estos elementos de configuración y diferentes técnicas para acceder a ellos desde tu código de aplicación.

Preparación

Si no se ha creado, crea una Azure Function con el runtime de la función V2. Utilizaré la aplicación de función que creamos en el capítulo 4, Comprender la experiencia de desarrollador integrada de Visual Studio Tools.

Cómo hacerlo…

En esta receta, vamos a ver algunas maneras de acceder a los valores de configuración.

Acceder a la configuración de la aplicación y a las cadenas de conexión en el código de Azure Function

Sigue estos pasos:

  1. Crea elementos de configuración con la clave MyAppSetting y ConnectionStrings con la clave sqldb_connection en el archivo local. settings.json. local.settings.json debe tener el aspecto que se muestra en la siguiente captura de pantalla:
  • Reemplaza el código existente por el código siguiente. Hemos agregado algunas líneas que leen los valores de configuración y las cadenas de conexión:

public class HttpTriggerCSharpFromVS

 {

 [FunctionName(«HttpTriggerCSharpFromVS»)]  public static IActionResult Run([HttpTrigger(AuthorizationLevel. Anonymous, «get», «post», Route = null)]HttpRequest req,ILogger

logger)

 {

 var configuration = new ConfigurationBuilder()

 .AddEnvironmentVariables()

 .AddJsonFile(«appsettings.json», true)

 .Build();

var ValueFromGetConnectionStringOrSetting = configuration.GetConne

ctionStringOrSetting(«MyAppSetting»);

 logger.LogInformation(«GetConnectionStringOrSetting» + ValueFromGetConnectionStringOrSetting);

var ValueFromConfigurationIndex= configuration[«MyAppSetting»];  logger.LogInformation(«ValueFromConfigurationIndex» + ValueFromConfigurationIndex);

var ValueFromConnectionString = configuration.GetConnectionStringO

rSetting(«ConnectionStrings:sqldb_connection»);

 logger.LogInformation(«ConnectionStrings:sqldb_connection» + ValueFromConnectionString); string name = req.Query[«name»];

 return name != null ? (ActionResult)new OkObjectResult($»Hello,

{name}»)

 : new BadRequestObjectResult(«Please pass a name on the query

string or in the request body»);

 }

}

  • Publica el proyecto en Azure haciendo clic con el botón derecho en el proyecto y en Publicar en el menú.
  • Agrega la clave de configuración y la cadena de conexión en la hoja Configuración de la aplicación:
  • Ejecuta la función haciendo clic en el botón Ejecutar, que registra los resultados en la ventana de resultados:

Configuración de la aplicación: expresiones de enlace

En la sección anterior, aprendimos a acceder a los valores de configuración desde el código. A veces, es posible que también desees configurar algunos de los elementos declarativos. Eso se puede lograr usando una expresión de enlace. Comprenderás lo que quiero decir en unos momentos, cuando miremos el código:

  1. Abre Visual Studio y realiza los cambios en el método Run para agregar un nuevo parámetro para configurar QueueTrigger:
  • El parámetro hardcodedqueuename es el nombre de la cola en la que se crearán los mensajes. Es obvio que codificar el nombre de la cola no es una buena práctica. Para poder configurarlo, debes utilizar la expresión de enlace de la configuración de la aplicación:
  • La clave de configuración de la aplicación debe estar incluida en %…% y se debe crear una clave con el nombre queuename en la configuración de la aplicación.

Crear y generar especificaciones de API abierta utilizando Swagger

Para un desarrollador de API web de back-end, una de sus responsabilidades es proporcionar una documentación adecuada a los desarrolladores de aplicaciones front-end para que puedan consumir las API sin ningún problema. Para poder consumir cualquier API, a continuación detallamos los dos conceptos mínimos que se deben comprender:

  • Los parámetros de entrada y sus tipos de datos
  • Los parámetros de salida y sus tipos de datos

Por lo tanto, es responsabilidad de los desarrolladores de back-end proporcionar la documentación adecuada para las API; esto no es tarea fácil, ya que hay muchas herramientas y normas/especificaciones disponibles para proporcionar la documentación adecuada para las API de REST. Una de estas normas se conoce como la especificación de API abierta (popularmente conocida como Swagger).

Azure Functions nos proporciona el soporte de herramientas necesario para generar las definiciones de API abierta para nuestros desencadenadores de HTTP. En esta receta, vamos a aprender a generarlas.

Preparación

Crea una función y uno o varios desencadenadores de HTTP. Para simplificarlo, he creado una aplicación de función y un desencadenador de HTTP, que solo acepta métodos Get.

Ten en cuenta que en el momento de la escritura, la función de definición de la API solo es compatible con el runtime de Azure Function V1.0 y aún está en modo preview. Todavía no funciona con la V2.

Comprueba que la aplicación Azure Function está configurada para apuntar a la versión 1 del runtime, como se muestra en la configuración de la aplicación:

Cómo hacerlo…

Sigue estos pasos:

  1. Desplázate hasta  las Características de la plataforma y haz clic en la pestaña Definición de API:
  • En la pestaña Definición de API, haz clic en la opción Función (Preview) para activar el origen de la definición de la API:
  • En cuanto hagas clic en el botón Función (Preview), se activará la función. Sin embargo, es posible que veas un error en la nueva pestaña indicando que aún está abierta. No te preocupes, ya que la característica aún está en modo preview; Microsoft podría corregirla antes de que esté disponible con carácter general (GA). A continuación, haz clic en Generar plantilla de definición de API:
  • Esto solo creará una plantilla de la definición de API abierta. Es responsabilidad del desarrollador en el cloud rellenar la plantilla, en función de las API que se hayan desarrollado. Debería tener el siguiente aspecto. Vamos a cambiar la plantilla en unos momentos:
  • En la captura de pantalla anterior, la pestaña Código contiene todas las plantillas predeterminadas necesarias para generar la definición de Swagger basada en la especificación de la API abierta. En la sección derecha se muestra cómo se ve la interfaz de usuario de Swagger. La interfaz de usuario de Swagger es algo que se compartirá con los otros equipos de desarrollo de la aplicación cliente que consumen las API de back-end.
  • Vamos a reemplazar la plantilla predeterminada agregando los parámetros requeridos de las operaciones de la API y vamos a hacer clic en el botón Guardar para guardar los cambios. Para simplificarlo, hemos realizado algunos cambios que describen la API y sus operaciones. Debería ser fácil de comprender.
  • La interfaz de usuario de Swagger tendrá el aspecto siguiente con los mensajes adecuados junto con los formatos de solicitud y respuesta:
  • También nos permite realizar algunas pruebas. Haz clic en el botón Probar esta operación que se muestra en la captura de pantalla anterior. Se abre una ventana donde puedes proporcionar entradas:
  • He introducido Praveen Kumar como valor para el nombre, he hecho clic en el botón Enviar solicitud y he obtenido el resultado siguiente:

Desglosar grandes API en pequeños subconjuntos de API usando proxies

Recientemente, una de las palabras de moda de la industria es «microservicios», donde desarrollas tus componentes web como microservicios que se pueden administrar (escalar, implementar, etc.) individualmente sin afectar a los otros componentes relacionados. Si bien el tema de los microservicios es enorme en sí mismo, intentaremos crear muy pocos microservicios que puedan administrarse individualmente como aplicaciones de función independiente. Pero, los expondremos al mundo externo como una única API con diferentes operaciones con la ayuda de los proxies de Azure Function.

Preparación

En esta receta, implementaremos la siguiente arquitectura:

Supongamos que estamos trabajando para un portal de comercio electrónico donde solo tenemos tres módulos (hombres, mujeres y niños) y nuestro objetivo es crear las API de back-end en una arquitectura de microservicios donde cada microservicio es independiente de los demás.

En esta receta, lo lograremos creando las siguientes aplicaciones de función:

  • Un componente de puerta de enlace (aplicación de función) que es responsable de controlar el tráfico al microservicio correcto en función de la ruta (/hombres, /mujeres y /niños). En esta aplicación de función, estaríamos creando proxies de Azure Function que redireccionarán el tráfico utilizando las configuraciones de ruta.
  • Tres nuevas aplicaciones de función donde cada una de ellas se trata como un microservicio separado.

Cómo hacerlo…

En esta receta, seguiremos estos pasos:

  1. Crear los tres microservicios con un desencadenador de HTTP en cada uno de ellos
  2. Crear, redirigir mediante proxy y configurar el microservicio respectivo
  3. Probar la dirección URL del proxy

Crear microservicios

Sigue estos pasos:

  1. Crea tres aplicaciones de función para cada uno de los microservicios que hemos planificado:
  • Crea los siguientes desencadenadores de HTTP anónimos en cada una de las aplicaciones de función que muestran un mensaje que tiene un aspecto similar al siguiente:
Nombre del desencadenador de HTTPMensaje de salida
Men-HttpTriggerHola, <<Nombre>>: bienvenido/a al microservicio Hombres
Women-HttpTriggerHola, <<Nombre>>: bienvenido/a al microservicio Mujeres
Kids-HttpTriggerHola, <<Nombre>>: bienvenido/a al microservicio Niños

Crear proxies de puerta de enlace

Sigue estos pasos:

  1. Ve a la aplicación de función de puerta de enlace y crea un nuevo proxy:
  • Serás redirigido a la hoja de detalles:
  • Crea los proxies para mujeres y niños. A continuación, encontrarás detalles de los tres proxies. Ten en cuenta que las direcciones URL de back-end  (de las aplicaciones de función) pueden ser diferentes en tu caso:
Nombre de proxyPlantilla de rutaDirección URL de back-end (las direcciones URL de los desencadenadores de HTTP creados en el paso anterior)
Hombres/Hombreshttps://azurefunctioncookbook-men. azurewebsites.net/api/Men-HttpTrigger
Mujeres/Mujereshttps://azurefunctioncookbook-women. azurewebsites.netapi/Women-HttpTrigger
Niños/Niñoshttps://azurefunctioncookbook-kids. azurewebsites.netapi/Kids-HttpTrigger
  • Después de crear los tres proxies, la lista deberá tener el aspecto siguiente:

Probar las direcciones URL de proxy

Como ya sabes, nuestros desencadenadores de HTTP aceptan un parámetro name requerido; es necesario que pasemos la cadena de consulta name a la dirección URL del proxy. Ahora, accederemos a las siguientes direcciones URL en el navegador:

  • Hombres:
  • Mujeres:
  • Niños:

Observa las direcciones URL de las tres capturas de pantalla. Verás que parece que se sirven desde una sola aplicación con diferentes rutas. Sin embargo, son tres microservicios diferentes que se pueden administrar individualmente.

Y eso no es todo…

Todos los microservicios que hemos creado en esta receta son anónimos, lo que significa que son de acceso público para todas las personas. Para garantizar su seguridad, debes seguir cualquiera de los enfoques recomendados en el capítulo 9, Implementar prácticas recomendadas para Azure Functions.

Los proxies de Azure Function también te permiten interceptar la solicitud original y, en caso necesario, puedes agregar nuevos parámetros y pasarlos a la API de back-end. Del mismo modo, puedes agregar parámetros adicionales y devolver la respuesta a la aplicación cliente. Puedes obtener más información sobre los proxies de Azure Function en la documentación oficial en https://docs.microsoft.com/ azure/azure-functions/functions-proxies.

Consulta también

  • La receta Controlar el acceso a Azure Functions mediante claves de función del capítulo 9, Implementar prácticas recomendadas para Azure Functions
  • La receta Proteger Azure Functions utilizando Azure AD del capítulo 9, Implementar prácticas recomendadas para Azure Functions
  • La receta Configurar la limitación de Azure Functions utilizando API Management incluida en el capítulo 9, Implementar prácticas recomendadas para Azure Functions

Mover elementos de configuración de un entorno a otro usando recursos

Todas las aplicaciones que desarrolles tendrán muchos elementos de configuración (como la configuración de aplicación como cadenas de conexión) que se almacenarán en los archivos Web.Config de todas tus aplicaciones web basadas en .NET.

En el mundo on-premise tradicional, el archivo Web.Config se ubicaría en el servidor y sería accesible para todas las personas que tienen acceso al servidor. Aunque es posible cifrar todos los elementos de configuración de Web.Config, tiene sus limitaciones; además, no es sencillo descifrarlos cada vez que quieres verlos o actualizarlos.

En el mundo PaaS de Azure, con Azure App Services, puedes tener los archivos Web. Config, que funcionan como solían hacerlo en el mundo on-premise tradicional. Sin embargo, Azure App Service nos proporciona una característica adicional en términos de configuración de la aplicación, donde puedes configurar estas opciones (ya sea manualmente o mediante plantillas de ARM), que se almacenan en un formato cifrado. Pero se pueden mostrar como texto normal en el portal si dispones de acceso.

Dependiendo del tipo de aplicación, el número de configuraciones de la aplicación puede aumentar hasta un gran tamaño; si deseas crear nuevos entornos, la creación de estas configuraciones de la aplicación tardará bastante tiempo. En esta receta, descubriremos el consejo de exportar e importar estas configuraciones de la aplicación desde un entorno inferior (por ejemplo, Dev) a un entorno superior (por ejemplo, Prod).

Preparación

Sigue estos pasos:

1. Si aún no está creada, crea una aplicación de función (por ejemplo,  MyApp-Dev)

3. Crea otra aplicación de función (por ejemplo, MyApp-Prod)

En esta receta, veremos lo fácil que es copiar la configuración de la aplicación de una función a otra. Esta técnica será útil cuando haya muchas configuraciones de aplicaciones.

Cómo hacerlo…

Sigue estos pasos:

  1. Ve a la pestaña Características de la plataforma de la aplicación de función MyApp-Dev y haz clic en Explorador de recursos:
  • Se abrirá el Explorador de recursos, desde donde puedes desplazarte por todos los elementos internos de un servicio determinado:
  • Haz clic en el elemento config, como se muestra en la captura de pantalla anterior, que abre todos los elementos relacionados con las configuraciones:
  • El Explorador de recursos mostrará todas las configuraciones de la aplicación en la ventana de la derecha. Ahora, puedes editarlas haciendo clic en el botón Editar, que aparece resaltado en la captura de pantalla anterior, o puedes copiar todas las configuraciones de la aplicación de AppSetting0 a AppSetting 9.
  • Desplázate hasta la aplicación de función MyApp-Prod (cuyas configuraciones de la aplicación no aparecen resaltadas en la captura de pantalla anterior), haz clic en el Explorador de recursos y, a continuación, haz clic en los elementos config | appsettings para abrir las configuraciones de la aplicación existentes. Debería tener el siguiente aspecto:
  • Haz clic en el botón Editar y pega el contenido que copiaste anteriormente. Una vez revisadas las configuraciones, haz clic en PUT, que se muestra en la captura de pantalla anterior.
  • Ve a la hoja de configuración de la aplicación de la aplicación de función MyApp-Prod:

Deberías ver todas las configuraciones de la aplicación que hemos creado en el Explorador de recursos en una sola imagen.