Você está na página 1de 394

Computación

sin servidor
de Azure
Libro de Segunda edición

instrucciones
Recetas para compilar y supervisar aplicaciones basadas en eventos mediante
Azure Functions

www.packt.com
Praveen Kumar Sreeram
Libro de instrucciones
de la computación sin
servidor de Azure
Segunda edición

Recetas para compilar y supervisar aplicaciones


basadas en eventos mediante Azure Functions

Praveen Kumar Sreeram

BIRMINGHAM - BOMBAY
Libro de instrucciones de la computación sin
servidor de Azure
Segunda edición
Copyright © 2018 Packt Publishing

Todos los derechos reservados. Ninguna parte de este libro puede reproducirse,
almacenarse en un sistema de recuperación o transmitirse en cualquier formato o por
cualquier medio, sin el permiso previo por escrito del editor, excepto en el caso de citas
breves incluidas en reseñas o artículos críticos.
En aras de asegurar la exactitud de la información presentada, se han realizado todos los
esfuerzos posibles en la preparación de este libro. No obstante, la información contenida
en él se proporciona sin garantía, ya sea expresa o implícita. Ni el autor ni Packt
Publishing o sus filiales y distribuidores, serán responsables de cualquier daño causado
o presuntamente causado por este libro ya sea de forma directa o indirecta.
Si bien Packt Publishing ha procurado suministrar información sobre las marcas
comerciales de todas las empresas y productos mencionados en este libro mediante el uso
correspondiente de mayúsculas, no puede garantizar la exactitud de esta información.
Editor responsable: Vijin Boricha
Editor de adquisiciones: Shrilekha Inani
Editores de desarrollo de contenido: Nithin George Varghese
Editor técnico: Komal Karne
Editor de copias: Safis Editing
Coordinador del proyecto: Drashti Panchal
Corrector: Safis Editing
Encargado de los índices: Mariammal Chettiyar
Gráficos: Tom Scaria
Coordinador de producción: Aparna Bhagat

Primera publicación: agosto de 2017


Segunda edición: noviembre de 2018

Referencia de producción: 1301118

Publicado por Packt Publishing Ltd.


Livery Place
35 Livery Street
Birmingham B3 2PB, Reino Unido.

ISBN 978-1-78961-526-5

www.packtpub.com
No habría podido terminar el libro sin el apoyo de mi media naranja,
mi esposa Haritha y mi angelito Rithwika Sreeram
mapt.io

Mapt es una biblioteca digital online que te otorga acceso a más de 5000 libros
y vídeos, así como a herramientas líderes del sector que te ayudan a planear tu
desarrollo personal y a avanzar en tu trayectoria profesional. Para obtener más
información, visita nuestro sitio web.

¿Por qué suscribirte?


• Pasa menos tiempo aprendiendo y más tiempo programando con prácticos
e-books y vídeos de más de 4000 profesionales del sector
• Aprende mejor con planes de aprendizaje diseñados especialmente para ti
• Consigue un e-book gratuito o un vídeo cada mes
• Mapt tiene una función de búsqueda completa
• Capacidad para copiar, pegar, imprimir y marcar contenidos

PacktPub.com
¿Sabías que Packt ofrece versiones en e-book de cada libro publicado en formato PDF
y ePub? Puedes actualizarte a la versión de e-book en www.PacktPub.com y, como
cliente de libros impresos, tienes derecho a un descuento en la copia del e-book.
Ponte en contacto con nosotros en la dirección de correo electrónico service@
packtpub.com para obtener más información.

En www.PacktPub.com, también podrás leer una colección de artículos técnicos


gratuitos, inscribirte en una gran variedad de boletines gratuitos y recibir descuentos
y ofertas exclusivos en libros y e-books de Packt.
Colaboradores

Acerca del autor


Praveen Kumar Sreeram trabaja como arquitecto de Azure y formador en una
importante empresa multinacional. Tiene más de 14 años de experiencia en el campo
del desarrollo, análisis, diseño y entrega de aplicaciones, incluido el desarrollo
web personalizado mediante ASP.NET y MVC para compilar aplicaciones móviles
con Xamarin para dominios como los seguros, las telecomunicaciones y la gestión
inalámbrica de gastos. Ha recibido dos veces el reconocimiento de profesional
más valioso (MVP) por parte de uno de los principales sitios web de comunidades
sociales, CSharpCorner. Es un bloguero entusiasta que escribe sobre su aprendizaje
en su blog personal, denominado Praveen Kumar Sreeram. En la actualidad se
centra en analizar problemas empresariales y proporcionar soluciones técnicas para
distintos proyectos relacionados con Microsoft Azure y .NET Core. Su ID de Twitter
es @PrawinSreeram.

En primer lugar, quisiera dar las gracias al equipo de Packt Publishing,


incluidos Shrilekha Inani, Nithin George Varghese y Komal Karne.

Quiero agradecer a mi abuela Neelavatamma, a mi padre Kamalakar y a mi


madre Seetha por acompañarme en mi vida y darme valor en todo momento.

Quería expresar mi más profunda gratitud a Bhagyamma (mi abuela),


Kamala Kumar (mi tío materno), sus hermanos y el resto de la familia que
tanto me han apoyado.
Acerca de los revisores
Kasam Shaikh, entusiasta de Microsoft Azure, es un profesional experimentado
con una actitud positiva, con 10 años de experiencia en el sector como arquitecto del
cloud con una de las principales empresas de TI de Bombay (India). Es un arquitecto
de Azure certificado, ha recibido el reconocimiento de MVP de una comunidad
online líder y también es ponente sobre IA a nivel mundial. Ha escrito libros sobre
Azure Cognitive, Azure Bots y Microsoft Bot Frameworks. Es el director de la
comunidad de Azure India (AZINDIA), la comunidad online de mayor crecimiento
para el aprendizaje de Azure. También es el fundador del sitio web Dear Azure.

Ante todo, me gustaría agradecer a Dios Todopoderoso, a mi familia y


sobre todo a mi media naranja, por motivarme a lo largo de este proceso.
Agradezco inmensamente a Packt Publishing que hayan pensado en mí para
esta oportunidad.

Michael Sync (Soe Htike) es ingeniero sénior y trabaja en Readify en Australia.


Ha sido MVP (profesional más valioso) durante 7 años. Ha participado como
ponente, mentor y ayudante en varios eventos comunitarios. También es autor y
revisor de libros de tecnología. Ha publicado dos libros con Manning y ha revisado
varios libros para distintos editores. Lleva más de 16 años trabajando en el sector del
software.

Packt busca a autores como tú


Si quieres convertirte en autor para Packt, visita authors.packtpub.com y solicita
un puesto. Hemos trabajado con miles de desarrolladores y profesionales de la
tecnología, igual que tú, para ayudarles a compartir sus conocimientos con la
comunidad técnica global. Puedes enviar una solicitud general, sobre un tema
específico para el que estemos reclutando autores o presentar tu propia idea.
Contenido
Prefacioxiii
Capítulo 1: Desarrollar aplicaciones en el cloud mediante
desencadenadores y enlaces de funciones 1
Introducción1
Crear una API web back-end mediante desencadenadores de HTTP 2
Preparación3
Cómo hacerlo... 3
Cómo funciona... 8
Consulta también 8
Almacenar datos del empleado mediante enlaces
de salida de tablas de Azure Storage 8
Preparación9
Cómo hacerlo... 9
Cómo funciona... 13
Comprender la conexión de almacenamiento 14
¿Qué es el servicio almacenamiento de tablas de Azure? 15
Clave de partición y clave de fila 15
Y eso no es todo… 15
Guardar las imágenes de perfil en colas utilizando
los enlaces de salida de cola 15
Preparación16
Cómo hacerlo... 16
Cómo funciona... 18
Almacenar la imagen en Azure Blob Storage 18
Preparación18
Cómo hacerlo... 18
Cómo funciona... 20
Y eso no es todo… 21

[i]
Contenido

Capítulo 2: Trabajar con notificaciones mediante los servicios


SendGrid y Twilio 23
Introducción23
Enviar una notificación por correo electrónico al administrador
de un sitio web mediante el servicio SendGrid 24
Preparación24
Creación de una cuenta de SendGrid 24
Generar una clave de API desde el portal de SendGrid 27
Configurar la clave de API de SendGrid con la aplicación Azure Function 28
Cómo hacerlo... 28
Crear un enlace de la cola de almacenamiento al desencadenador de HTTP 29
Crear un desencadenador de cola para procesar el mensaje del
desencadenador de HTTP 30
Crear un enlace de salida de SendGrid al desencadenador de cola 31
Cómo funciona... 33
Y eso no es todo 34
Enviar una notificación de correo electrónico dinámicamente
al usuario final 34
Preparación34
Cómo hacerlo... 35
Aceptar el nuevo parámetro de correo electrónico en la función RegisterUser 35
Recuperar la información de UserProfile en el desencadenador SendNotifications 36
Cómo funciona... 37
Y eso no es todo… 38
Implementar el registro de correo electrónico en Azure Blob Storage 39
Cómo hacerlo... 39
Cómo funciona... 41
Modificar el contenido del correo electrónico para incluir
un archivo adjunto 41
Preparación42
Cómo hacerlo... 42
Personalizar el nombre del archivo de registro utilizando la interfaz IBinder 42
Agregar un archivo adjunto al correo electrónico 43
Enviar una notificación por SMS al usuario final utilizando
el servicio Twilio 44
Preparación45
Cómo hacerlo... 47
Cómo funciona... 49
Capítulo 3: Integración perfecta de Azure Functions
con los Servicios de Azure 51
Introducción51
Usar Cognitive Services para identificar caras en imágenes 52

[ ii ]
Contenido

Preparación52
Crear una nueva cuenta de Computer Vision API 52
Ajustar la configuración de la aplicación 53
Cómo hacerlo... 53
Cómo funciona... 60
Y eso no es todo… 60
Interacciones de Azure SQL Database mediante Azure Functions 61
Preparación61
Cómo hacerlo... 63
Cómo funciona... 66
Supervisar tweets a través de Logic Apps y notificar
a los usuarios publicaciones de tweets de usuarios populares 66
Preparación67
Cómo hacerlo... 67
Crear una Logic App nueva 67
Diseñar la Logic App con conectores de Twitter y Gmail 69
Probar la funcionalidad de Logic App 73
Cómo funciona... 74
Integrar Logic Apps con funciones sin servidor 74
Cómo hacerlo... 75
Y eso no es todo… 79
Consulta también 80
Auditorías de datos de Cosmos DB mediante desencadenadores
de fuente de cambios 80
Preparación80
Crear una nueva cuenta de Cosmos DB 81
Crear una nueva colección de Cosmos DB 81
Cómo hacerlo... 82
Cómo funciona... 86
Y eso no es todo… 86
Capítulo 4: Comprender la experiencia de desarrollador
integrada de Visual Studio Tools 87
Introducción 87
Crear una aplicación de función con Visual Studio 2017 88
Preparación88
Cómo hacerlo... 90
Cómo funciona... 92
Y eso no es todo… 92
Depurar Azure Functions de C# en un entorno preconfigurado
local usando Visual Studio 2017 92
Preparación93
Cómo hacerlo... 93
[ iii ]
Contenido

Cómo funciona... 97
Y eso no es todo… 97
Cómo conectarse al cloud de Azure Storage desde el entorno
local de Visual Studio 98
Preparación98
Cómo hacerlo... 98
Cómo funciona... 102
Y eso no es todo… 102
Implementar la aplicación Azure Function en Azure Cloud
mediante Visual Studio 103
Cómo hacerlo... 103
Y eso no es todo… 107
Depurar en vivo Azure Function de C#, que se hospeda
en el entorno en el cloud de Microsoft Azure, utilizando
Visual Studio 107
Preparación108
Cómo hacerlo... 108
Implementar Azure Functions en un contenedor 111
Preparación112
Creación de un ACR 113
Cómo hacerlo... 114
Crear una imagen de Docker para la aplicación de función 115
Insertar la imagen de Docker en el ACR 116
Crear una nueva aplicación de función con Docker 118
Cómo funciona... 119
Capítulo 5: Explorar las herramientas de pruebas
para la validación de Azure Functions 121
Introducción121
Probar Azure Functions 122
Preparación122
Cómo hacerlo... 123
Probar los desencadenadores de HTTP mediante Postman 123
Probar un desencadenador de blob mediante el explorador de Microsoft Storage 125
Probar el desencadenador de cola mediante el portal de administración de Azure 128
Y eso no es todo… 131
Probar una función de Azure en un entorno preconfigurado
mediante ranuras de implementación 131
Cómo hacerlo... 132
Y eso no es todo… 139
Realizar pruebas de carga de Azure Functions mediante
Azure DevOps  139

[ iv ]
Contenido

Preparación140
Cómo hacerlo... 140
Y eso no es todo… 143
Consulta también 144
Crear y probar Azure Functions a nivel local mediante
herramientas de CLI de Azure 144
Preparación145
Cómo hacerlo... 145
Probar y validar la capacidad de respuesta de la función
de Azure mediante Application Insights 148
Preparación149
Cómo hacerlo... 150
Cómo funciona... 153
Y eso no es todo… 153
Desarrollar pruebas unitarias para Azure Functions
con desencadenadores de HTTP 153
Preparación154
Cómo hacerlo... 155
Capítulo 6: Supervisar y solucionar problemas de los servicios
de Azure sin servidor 158
Introducción158
Solucionar problemas de Azure Functions 159
Cómo hacerlo... 159
Ver registros de aplicaciones en tiempo real 159
Diagnosticar la aplicación de funciones completa 161
Y eso no es todo… 162
Integrar Azure Functions con Application Insights 164
Preparación164
Cómo hacerlo... 165
Cómo funciona... 167
Y eso no es todo… 167
Supervisar Azure Functions 167
Cómo hacerlo... 167
Cómo funciona... 169
Insertar datos de telemetría personalizados
en Application Insights Analytics 169
Preparación171
Cómo hacerlo... 171
Crear una función de Application Insights 172
Configurar claves de acceso 173
Integrar y probar una consulta de Application Insights 175

[v]
Contenido

Configurar el informe de métrica derivada personalizada 177


Cómo funciona... 179
Enviar datos de telemetría de la aplicación por correo electrónico 180
Preparación180
Cómo hacerlo... 181
Cómo funciona... 183
Y eso no es todo… 183
Consulta también 183
Integrar datos de supervisión de Application Insights en tiempo
real con Power BI mediante Azure Functions 183
Preparación184
Cómo hacerlo... 185
Configurar Power BI con un panel, un conjunto de datos y el URI de inserción 185
Crear una función C# de Power BI en tiempo real para Azure Application Insights 191
Cómo funciona... 194
Y eso no es todo… 194
Capítulo 7: Desarrollar aplicaciones fiables sin servidor
mediante Durable Functions 196
Introducción196
Configurar Durable Functions en el portal de administración
de Azure 197
Preparación197
Cómo hacerlo... 198
Y eso no es todo… 199
Crear una aplicación Hola, mundo de Durable Functions 200
Preparación200
Cómo hacerlo... 200
Crear una función HttpStart en el cliente de orquestador 201
Crear la función de orquestador 203
Crear una función de actividad 205
Cómo funciona... 206
Y eso no es todo… 206
Probar y solucionar problemas de Durable Functions 206
Preparación207
Cómo hacerlo... 207
Implementar aplicaciones fiables multiproceso mediante Durable
Functions209
Preparación209
Cómo hacerlo... 210
Crear la función de orquestador 210
Crear una función de actividad GetAllCustomers  211
Crear una función de actividad CreateBARCodeImagesPerCustomer 212

[ vi ]
Contenido

Cómo funciona... 214


Y eso no es todo... 214
Capítulo 8: Importación masiva de datos mediante
Cosmos DB y Durable Functions de Azure 216
Introducción216
Problema empresarial 217
Una forma duradera y sin servidor de implementar
una importación de Excel 218
Cargar datos de empleados en Blob Storage 218
Cómo hacerlo... 219
Cómo funciona... 222
Y eso no es todo… 223
Crear un desencadenador de blob 223
Preparación223
Cómo hacerlo... 227
Y eso no es todo… 227
Crear el orquestador durable y activarlo para cada
importación de Excel 228
Cómo hacerlo... 228
Cómo funciona... 231
Y eso no es todo… 231
Leer datos de Excel mediante funciones de actividad 232
Preparación232
Cómo hacerlo... 233
Leer datos de Blob Storage 233
Leer datos de Excel desde la secuencia 234
Crear la función de actividad 235
Y eso no es todo… 237
Escalar automáticamente el rendimiento de Cosmos DB 238
Preparación238
Cómo hacerlo... 240
Y eso no es todo… 242
Insertar masivamente datos en Cosmos DB 242
Cómo hacerlo... 242
Y eso no es todo… 243
Capítulo 9: Implementar prácticas recomendadas para
Azure Functions 244
Agregar varios mensajes a una cola
mediante la función IAsyncCollector 245
Preparación245

[ vii ]
Contenido

Cómo hacerlo... 246


Cómo funciona... 248
Y eso no es todo… 248
Implementar aplicaciones defensivas con Azure Functions
y desencadenadores de cola 248
Preparación249
Cómo hacerlo... 249
CreateQueueMessage: aplicación de consola de C# 249
Desarrollar la Azure Function: desencadenador de cola 250
Ejecutar pruebas mediante la aplicación de consola 251
Cómo funciona... 252
Y eso no es todo… 252
Administrar entradas masivas mediante Event Hubs para
IoT y otros escenarios similares 253
Preparación253
Cómo hacerlo... 253
Crear un desencadenador de centro de eventos de la Azure Function  253
Desarrollar una aplicación de consola que simule los datos de IoT  254
Evitar arranques en frío activando la aplicación periódicamente 257
Preparación257
Cómo hacerlo... 258
Crear un desencadenador de HTTP 258
Crear un desencadenador de temporizador 258
Y eso no es todo… 259
Consulta también 259
Habilitar autorización para aplicaciones de función 259
Preparación259
Cómo hacerlo... 260
Cómo funciona... 261
Y eso no es todo… 261
Controlar el acceso a Azure Functions mediante claves de función 261
Cómo hacerlo... 262
Configurar la clave de función para cada aplicación 262
Configurar una clave de host para todas las funciones en una sola
aplicación de función 263
Y eso no es todo… 265
Proteger Azure Functions mediante Azure Active Directory 265
Preparación266
Cómo hacerlo... 266
Configurar Azure AD para la Function App 266
Registrar la aplicación cliente en Azure AD 267
Conceder a la aplicación cliente acceso a la aplicación de back-end  270
Probar la funcionalidad de autenticación mediante un token JWT 270

[ viii ]
Contenido

Configurar la limitación de Azure Functions mediante


API Management 272
Preparación273
Cómo hacerlo... 274
Integrar Azure Functions con API Management 274
Configurar la limitación de solicitudes mediante políticas de entrada 277
Probar la configuración de política de entrada de límite de velocidad 279
Cómo funciona... 280
Acceder de forma segura a SQL Database desde Azure Functions
mediante Managed Service Identity 281
Preparación281
Cómo hacerlo... 282
Crear una aplicación de función con Visual Studio 2017 con el runtime v1 282
Crear un SQL Server lógico y una SQL Database 285
Habilitar la Managed Service Identity 285
Y eso no es todo… 288
Consulta también 288
Código compartido en Azure Functions mediante
bibliotecas de clases 288
Cómo hacerlo... 289
Cómo funciona... 291
Y eso no es todo… 292
Usar clases fuertemente tipadas en Azure Functions 292
Preparación292
Cómo hacerlo... 293
Cómo funciona... 295
Y eso no es todo… 295
Capítulo 10: Configurar aplicaciones sin servidor en el entorno
de producción 296
Introducción296
Implementar Azure Functions mediante Ejecutar desde el paquete 297
Preparación298
Cómo hacerlo... 299
Cómo funciona... 300
Y eso no es todo… 300
Implementar Azure Function mediante plantillas de ARM 300
Preparación300
Cómo hacerlo... 301
Y eso no es todo… 304
Configurar un dominio personalizado en Azure Functions 304
Preparación305

[ ix ]
Contenido

Cómo hacerlo... 305


Configurar la aplicación de función con un dominio existente 307
Técnicas para acceder a la configuración de la aplicación 309
Preparación309
Cómo hacerlo... 309
Acceder a la configuración de la aplicación y a las cadenas de conexión
en el código de Azure Function 309
Configuración de la aplicación: expresiones de enlace  312
Crear y generar especificaciones de API abierta utilizando Swagger 312
Preparación313
Cómo hacerlo... 313
Desglosar grandes API en pequeños subconjuntos
de API usando proxies 317
Preparación317
Cómo hacerlo... 318
Crear microservicios 319
Crear proxies de puerta de enlace 319
Probar las direcciones URL de proxy 322
Y eso no es todo… 322
Consulta también 323
Mover elementos de configuración de un entorno
a otro usando recursos 323
Preparación324
Cómo hacerlo... 325
Capítulo 11: Implementar la integración continua mediante
Azure DevOps 330
Introducción330
Requisitos previos 331
Integración continua: crear una definición de compilación 332
Preparación333
Cómo hacerlo... 334
Cómo funciona... 338
Y eso no es todo… 339
Integración continua: poner en cola una compilación
y desencadenarla manualmente 339
Preparación339
Cómo hacerlo... 340
Configurar y desencadenar una compilación automatizada 342
Cómo hacerlo... 343
Cómo funciona... 345
Y eso no es todo… 345

[x]
Contenido

Integración continua: ejecutar casos de pruebas unitarias


en la canalización 346
Cómo hacerlo 347
Y eso no es todo… 349
Crear una definición de versión 349
Preparación350
Cómo hacerlo... 351
Cómo funciona... 359
Y eso no es todo… 359
Consulta también 360
Desencadenar la versión automáticamente 361
Preparación361
Cómo hacerlo... 361
Cómo funciona... 363
Y eso no es todo… 363
Otros libros que te podrían gustar 364

[ xi ]
Prefacio

Prefacio
La informática sin servidor es la abstracción de la administración de infraestructura
y permite a los desarrolladores aumentar su enfoque en la lógica empresarial para que
puedan ofrecer más funciones e innovación por ciclo. Al crear aplicaciones sin servidor,
no tienes que invertir tiempo en administrar o aprovisionar la infraestructura (por
ejemplo, crear servidores, instalar actualizaciones, aplicar revisiones del SO, administrar
la escala de la aplicación). En su lugar, utiliza un conjunto de servicios en el cloud
totalmente escalables y administrados que se encargan de esa parte del trabajo.
Los beneficios de la informática sin servidor abarcan todo el ciclo de organización
y desarrollo:
• Para el desarrollador, representa un enfoque total en el valor. La creación
de aplicaciones sin servidor aumenta la capacidad individual para contribuir
de manera más efectiva al núcleo del negocio.
• Para el equipo de desarrollo, significa un tiempo de comercialización más
rápido. Un enfoque sin servidor aumenta su velocidad para ofrecer más valor
por ciclo de desarrollo.
• Para la organización, es un habilitador de la innovación desde una
base sólida. Gracias a la combinación de capacidad liberada y servicios
incorrectos, toda la organización puede actuar en las primeras señales para
desarrollar o diversificar su modelo empresarial y cumplir con su agenda
de innovación.
Cuando hablamos de aplicaciones sin servidor, podemos identificar algunos
patrones de aplicaciones que vale la pena mencionar aquí. Si bien cada uno de ellos
comparte las ventajas mencionadas anteriormente, también tienen características
específicas y ventajas adicionales que los hacen únicos y se adaptan mejor a ciertos
escenarios. Aquí están los patrones de aplicaciones sin servidor que podemos
observar:
• Las aplicaciones web, que alojan tanto el lado del back-end como el del
cliente en un servicio totalmente administrado que se ocupa de los requisitos
de escalado, seguridad y cumplimiento automáticos, con App Service.
[ xiii ]
Prefacio

• Aplicaciones controladas por eventos que utilizan funciones sin


servidor, aprovechando el modelo de programación único (basado en
desencadenadores para responder a eventos y enlaces para integrar otros
servicios) y un modelo de facturación de pago por ejecución, con Azure
Functions.
• Los flujos de trabajo con poco código para una orquestación fácil
y rápida de tareas combinadas que resuelven un problema empresarial
(que generalmente integra diferentes servicios, tanto en el cloud como
on-premises, para trabajar conjuntamente) sin en realidad codificar esas
integraciones, ni aprender nuevas API o especificaciones, con Logic Apps.
• Los contenedores sin servidor, llevando tus propios contenedores a una
orquestación de Kubernetes completamente administrada con Azure
Kubernetes Service que puede hacer escalados en ráfaga con nodos virtuales
y Azure Container Instances cuando el volumen de la carga de trabajo
aumenta de forma repentina o de golpe.
Microsoft proporciona una solución para ejecutar fácilmente pequeños segmentos
de código en el cloud con Azure Functions. Azure Functions proporciona soluciones
para procesar datos, integrar sistemas y crear API y microservicios simples.
El libro comienza con recetas de nivel intermedio en informática sin servidor,
junto con algunos casos de uso sobre las ventajas y características clave de Azure
Functions. Luego, profundizaremos en los aspectos principales de Azure Functions,
como los servicios que proporciona, cómo se puede desarrollar y escribir Azure
Functions y cómo supervisar y solucionar problemas de Azure Functions.
Después, obtendrás recetas prácticas sobre la integración de DevOps con Azure
Functions y la implementación continua con Azure DevOps (anteriormente Visual
Studio Team Services). El libro también proporciona pasos prácticos y tutoriales
basados en casos de uso sin servidor reales para guiarte a través de la configuración
y el ajuste de tus entornos sin servidor con facilidad. Finalmente, verás cómo
administrar Azure Functions, brindando seguridad y cumplimiento a nivel
empresarial a tu arquitectura de código sin servidor.
También aprenderás a crear rápidamente aplicaciones que sean fiables y duraderas
con Durable Functions, con un ejemplo de un caso de uso en tiempo real muy
común.
Al final de este libro, tendrás todas las habilidades necesarias para trabajar con
arquitecturas de código sin servidor, proporcionando una entrega continua a los
usuarios.

A quién está destinado este libro


Si eres un administrador en el cloud, arquitecto o desarrollador que quieres crear
sistemas escalables e implementar aplicaciones sin servidor con Azure Functions,
el Libro de instrucciones de la informática sin servidor de Azure es para ti.
[ xiv ]
Prefacio

Temas tratados en este libro


En el capítulo 1, Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces
de funciones, se explica cómo el runtime de Azure Functions proporciona plantillas
que se pueden usar para integrar rápidamente diferentes servicios de Azure para las
necesidades de tu aplicación. Reduce todo el código de la base necesaria para que
puedas concentrarte solo en la lógica de tu aplicación. En este capítulo, aprenderás
a crear API web y enlaces relacionados con los servicios de Azure Storage.

El capítulo 2, Trabajar con notificaciones mediante los servicios SendGrid y Twilio,


se ocupa de cómo la comunicación es uno de los aspectos más importantes de
cualquier requisito empresarial. En este capítulo, aprenderás lo fácil que es conectar
tus requisitos empresariales escritos en Azure Functions con los servicios de
comunicación más populares, como SendGrid (para correo electrónico) y Twilio
(para SMS).

En el capítulo 3, Integración perfecta de Azure Functions con los Servicios de Azure, se


explica cómo Azure proporciona muchos conectores que podrías aprovechar para
integrar tus aplicaciones empresariales con otros sistemas con bastante facilidad. En
este capítulo, descubrirás cómo integrar Azure Functions con servicios cognitivos
y aplicaciones lógicas.

El capítulo 4, Comprender la experiencia de desarrollador integrada de Visual Studio Tools


para Azure Functions, te enseña cómo desarrollar Azure Functions usando Visual
Studio, que brinda muchas características como Intellisense, depuración local
y remota y la mayoría de las funciones de desarrollo habituales.

El capítulo 5, Explorar herramientas de prueba para la validación de Azure Functions, te


ayuda a comprender diferentes herramientas y procesos útiles para optimizar tus
procesos de desarrollo y control de calidad. También aprenderás a crear cargas
usando las pruebas de carga de Azure DevOps (anteriormente VSTS) y verás
cómo supervisar el rendimiento de Azure Functions utilizando los informes
proporcionados por Application Insights. Finalmente, también aprenderás
a configurar alertas que te notifiquen cuando las aplicaciones no responden.

El capítulo 6, Supervisar y solucionar problemas de servicios de Azure sin servidor, te


enseña cómo supervisar continuamente las aplicaciones, analizar el rendimiento
y revisar los registros para comprender si existen problemas para los usuarios finales.
Azure nos proporciona diversas herramientas para lograr todos nuestros requisitos
de supervisión, directamente desde las fases de desarrollo y mantenimiento.

El capítulo 7, Desarrollo de aplicaciones fiables sin servidor mediante Durable Functions, te


muestra cómo desarrollar soluciones de larga duración y con estado en entornos sin
servidor utilizando Durable Functions, que tiene características avanzadas que se
han lanzado como una extensión de Azure Functions.

[ xv ]
Prefacio

El capítulo 8, Importación masiva de datos mediante Cosmos DB y Durable Functions


de Azure, te enseña cómo aprovechar Durable Functions de Azure para leer
e importar los datos del almacenamiento de blobs y volcar los datos en Cosmos DB.

El capítulo 9, Implementar prácticas recomendadas para Azure Functions, te enseña


algunas de las prácticas recomendadas que debes seguir para mejorar el rendimiento
y la seguridad mientras trabajas en Azure Functions.

El capítulo 10, Configurar aplicaciones sin servidor en el entorno de producción, demuestra


cómo implementar una aplicación de función de una manera eficiente y copiar/
mover las configuraciones de una manera más inteligente para evitar errores
humanos. También aprenderás a configurar un dominio personalizado que podrías
compartir con tus clientes o usuarios finales en lugar del dominio predeterminado
que se crea como parte del aprovisionamiento de la aplicación de función.

El capítulo 11, Implementar la integración continua mediante Azure DevOps, te ayuda


a descubrir cómo implementar la integración y entrega continua del código de Azure
Functions con la ayuda de Visual Studio y Azure DevOps.

Para sacar el máximo partido a este libro


Se requieren conocimientos previos y experiencia práctica con los servicios
principales de Microsoft Azure.

Descargar los archivos de código de ejemplo


Puedes descargar los archivos de código de ejemplo para este libro desde tu cuenta
en http://www.packtpub.com. Si has comprado este libro en otro sitio, puedes
visitar http://www.packtpub.com/support y registrarte para recibir los archivos
por correo electrónico directamente.

Puedes descargar los archivos de código siguiendo estos pasos:

1. Inicia sesión o regístrate en http://www.packtpub.com.


2. Selecciona la pestaña SOPORTE.
3. Haz clic en Descargas de código y erratas.
4. Introduce el nombre del libro en la casilla de Búsqueda y sigue las
instrucciones en pantalla.

[ xvi ]
Prefacio

Tras descargar el archivo, asegúrate de descomprimir o extraer la carpeta con la


última versión de:

• WinRAR/7-Zip para Windows


• Zipeg/iZip/UnRarX para Mac
• 7-Zip/PeaZip para Linux

El paquete de códigos para el libro también se encuentra en GitHub en


https://github.com/PacktPublishing/Azure-Serverless-Computing-
Cookbook-Second-Edition. También tenemos otros paquetes de códigos de
nuestro rico catálogo de libros y vídeos disponibles en https://github.com/
PacktPublishing/. ¡Échales un vistazo!

Descargar los archivos EPUB/mobi y los


archivos de código de ejemplo
Una versión EPUB y mobi de este libro está disponible de forma gratuita en GitHub.

Descargar las imágenes en color


También te ofrecemos un archivo PDF que tiene imágenes en color de las capturas
de pantalla/diagramas que se utilizan en este libro. Puedes descargarlo aquí:
https://www.packtpub.com/sites/default/files/downloads/9781789615265_
ColorImages.pdf.

Convenciones utilizadas
Hay una serie de convenciones de texto que se utilizan a lo largo de este libro.

CódigoEnTexto: indica palabras de código en el texto, nombres de tablas de bases de


datos, nombres de carpetas, nombres de archivos, extensiones de archivo, rutas, URL
ficticias, entradas de usuario y alias de Twitter. Este es un ejemplo: "Monta el archivo
de imagen de disco descargado WebStorm-10*.dmg como otro disco en tu sistema."

Un bloque de código aparece de la siguiente forma:


using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

[ xvii ]
Prefacio

Cuando queremos llamar tu atención sobre una parte concreta de un bloque


de código, las líneas o elementos relevantes están en negrita:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

Una entrada o resultado de la línea de comandos se escribe así:


docker tag functionsindocker cookbookregistry.azurecr.io/
functionsindocker:v1

Negrita: indica que un nuevo término, una palabra importante o palabras que ves en
la pantalla, por ejemplo, en menús o cuadros de diálogo, que también aparecen en
este tipo de texto. Este es un ejemplo: "Durante la instalación, selecciona Desarrollo
de Azure en la sección Cargas de trabajo."

Las advertencias o las notas importantes


aparecen de esta forma.

Los consejos y trucos aparecen de esta forma.

Secciones
En este libro, encontrarás varios títulos que aparecen con frecuencia (Preparación,
Cómo hacerlo..., Cómo funciona..., Y eso no es todo... y Consulta también).

Para dar instrucciones claras sobre cómo completar una receta, usa estas secciones
de la siguiente manera:

Preparación
En esta sección se indica qué esperar en la receta y se describe cómo configurar
cualquier software o cualquier configuración preliminar necesaria para la receta.

Cómo hacerlo...
Esta sección contiene los pasos necesarios para seguir la receta.

[ xviii ]
Prefacio

Cómo funciona...
Esta sección generalmente consiste en una explicación detallada de lo que sucedió en
la sección anterior.

Y eso no es todo…
Esta sección contiene información adicional sobre la receta para que tengas más
conocimiento sobre la receta.

Consulta también
En esta sección se proporcionan enlaces útiles a otra información útil para la receta.

Habla con nosotros


Los comentarios de nuestros lectores siempre son bienvenidos.

Comentarios generales: envía un correo electrónico a feedback@packtpub.com


y menciona el título del libro en el asunto de tu mensaje. Si tienes preguntas acerca
de cualquier aspecto de este libro, envíanos un correo electrónico a questions@
packtpub.com.

Erratas: aunque hemos tenido muchísimo cuidado para asegurarnos de que


nuestro contenido sea correcto, siempre se producen errores. Si has encontrado
un error en este libro, te agradeceríamos que nos informaras de ello. Visita
http://www.packtpub.com/submit-errata, selecciona el libro, haz clic en el enlace
del formulario de aviso de erratas y escribe los detalles.

Piratería: si te encuentras con copias ilegales de nuestros trabajos en cualquier


formato en Internet, te rogamos que nos indiques la dirección o el nombre del sitio
web inmediatamente. Ponte en contacto con nosotros en copyright@packtpub.com
con un enlace al material.

Si te interesa convertirte en autor: si hay un tema en el que tengas experiencia


y te interesa escribir o contribuir a un libro, visita http://authors.packtpub.com.

[ xix ]
Prefacio

Reseñas
Nos encantaría que nos dejaras una reseña. Tras haber leído y utilizado este libro,
¿por qué no nos dejas una reseña en el sitio en el que lo hayas comprado? Los
lectores potenciales pueden ver tu opinión imparcial y realizar decisiones de compra
en función de ella, nosotros en Packt podemos entender qué opinas de nuestros
productos y nuestros autores podrán ver tus comentarios sobre su libro. ¡Muchas
gracias!

Para obtener más información acerca de Packt, visita packtpub.com.

[ xx ]
Desarrollar aplicaciones
en el cloud mediante
desencadenadores y enlaces
de funciones
En este capítulo, abordaremos las siguientes recetas:

• Crear una API web back-end mediante desencadenadores de HTTP


• Almacenar datos del empleado mediante enlaces de salida de tablas
de Azure Storage
• Guardar las imágenes de perfil en colas utilizando los enlaces de salida
de cola
• Almacenar la imagen en Azure Blob Storage

Introducción
Cada aplicación de software necesita componentes de back-end que sean
responsables de cuidar la lógica empresarial y almacenar los datos en algún tipo
de almacenamiento, como bases de datos y sistemas de archivos. Cada uno de estos
componentes de back-end podría desarrollarse utilizando diferentes tecnologías.
La tecnología sin servidor de Azure también nos permite desarrollar estas API
de back-end utilizando Azure Functions.

[1]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

Azure Functions proporciona muchas plantillas listas para usar que resuelven los
problemas más comunes, como la conexión al almacenamiento, la creación de API
web y el recorte de imágenes. En este capítulo, descubriremos cómo usar estas
plantillas integradas. Junto con el aprendizaje de los conceptos relacionados con la
computación sin servidor de Azure, también intentaremos implementar una solución
a un problema de dominio básico de creación de componentes necesarios para que
cualquier organización gestione la información de los empleados internos.

A continuación, vemos un diagrama simple que te ayuda a comprender lo que


lograremos en este capítulo:

Crear una API web back-end mediante


desencadenadores de HTTP
Usaremos la arquitectura sin servidor de Azure para crear una API web utilizando
desencadenadores de HTTP. Cualquier aplicación front-end capaz de realizar
llamadas HTTP puede consumir esos desencadenadores de HTTP.

[2]
Capítulo 1

Preparación
Comencemos nuestro viaje para comprender la informática sin servidor de Azure
utilizando Azure Functions mediante la creación de una API web back-end básica
que responde a las solicitudes HTTP:

• Consulta https://azure.microsoft.com/free/?&wt.mc_id=AID607363_
SEM_8y6Q27AS para crear una cuenta gratuita de Azure.
• Visita https://docs.microsoft.com/azure/azure-functions/
functions-create-function-app-portal para comprender el proceso
detallado de cómo crear una aplicación de función y https://docs.
microsoft.com/azure/azure-functions/functions-create-first-
azure-function crear una función. Al crear una función, también se crea
una cuenta de almacenamiento para almacenar todos los archivos. Recuerda
el nombre de la cuenta de almacenamiento, ya que se usará más adelante en
los otros capítulos.
• Después de crear la aplicación de función, desplázate por los conceptos
básicos de desencadenadores y enlaces, que son los conceptos fundamentales
de cómo funciona Azure Functions. Se recomienda encarecidamente que
leas el artículo https://docs.microsoft.com/azure/azure-functions/
functions-triggers-bindings antes de continuar.

En todo el libro, utilizaremos C# como lenguaje de programación.


La mayoría de las funciones se desarrollan usando el runtime de
Azure Functions V2. Sin embargo, hay algunas recetas que aún no
son compatibles con el runtime V2 que se menciona en la receta
respectiva. Con suerte, para cuando leas este libro, Microsoft
también habrá habilitado esas funciones para el runtime V2.

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate a la página de listas Function App haciendo clic en el menú


Function Apps, que está disponible en el lado izquierdo.
2. Crea una función nueva haciendo clic en el icono +:

[3]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

3. Verás la página Azure Functions para .NET: introducción, donde se te


pedirá que elijas el tipo de herramientas que te gustaría usar. Puedes
seleccionar la herramienta en la que estés interesado. En los primeros
capítulos, usaremos la opción En el portal, donde puedes crear rápidamente
Azure Functions desde el portal sin herramientas. Más adelante, en los otros
capítulos, usaremos Visual Studio y Azure Functions Core Tools para crear
las funciones:

4. En el paso siguiente, selecciona Más plantillas y haz clic en Finalizar y ver


plantillas como se muestra en la siguiente captura de pantalla:

[4]
Capítulo 1

5. En la sección Seleccionar una plantilla a continuación o ir al inicio


rápido, elige Desencadenador de HTTP para crear una nueva función
de Desencadenador de HTTP:

[5]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

6. Proporciona un nombre descriptivo. En este ejemplo, he usado


RegisterUser como nombre de la función de Azure.
7. En el menú desplegable Nivel de autorización, selecciona la opción
Anónimo. Aprenderemos más acerca de todos los niveles de autorización
en el capítulo 9, Implementar prácticas recomendadas para Azure Functions:

8. Haz clic en el botón Crear para crear la función de desencadenador de HTTP.


9. Tan pronto como crees la función, todos los códigos necesarios y los archivos
de configuración se crearán automáticamente y el archivo run.csx se abrirá
para que edites el código. Borra el código predeterminado y sustitúyelo por
el código siguiente. He agregado dos parámetros (firstname y lastname)
que se mostrarán en la salida cuando se desencadene el desencadenador
de HTTP:
#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(


HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a
request.");
string firstname=null,lastname = null;
string requestBody = await new StreamReader(req.Body).
ReadToEndAsync();

dynamic inputJson = JsonConvert.DeserializeObject(requestBody);


firstname = firstname ?? inputJson?.firstname;
lastname = inputJson?.lastname;

return (lastname + firstname) != null


? (ActionResult)new OkObjectResult($"Hello, {firstname + " " +
lastname}")
: new BadRequestObjectResult("Please pass a name on the query" +
"string or in the request body");
}

[6]
Capítulo 1

10. Guarda los cambios haciendo clic en el botón Guardar que se encuentra justo
encima del editor de código.
11. Intentemos probar la función RegisterUser usando la consola de prueba.
Haz clic en la pestaña Probar para abrir la consola de prueba:

12. Introduce los valores de firstname y lastname en la sección Cuerpo


de la solicitud:

Asegúrate de seleccionar POST en el menú desplegable Método HTTP.

13. Después de revisar los parámetros de entrada, haz clic en el botón Ejecutar
que se encuentra en la parte inferior de la consola de prueba:

[7]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

14. Si la carga de trabajo de la solicitud de entrada se pasa correctamente con


todos los parámetros necesarios, verás Estado 200 OK y la salida en la
ventana Salida se mostrará como en la captura de pantalla anterior.

Cómo funciona...
Hemos creado la primera función básica de Azure usando desencadenadores
de HTTP y hemos realizado algunas modificaciones en el código predeterminado.
El código simplemente acepta los parámetros firstname y lastname e imprime
el nombre del usuario final con un mensaje Hola {firstname} {lastname} como
respuesta. También hemos visto cómo probar la función de desencadenador de
HTTP directamente desde el portal de administración de Azure.

En aras de la simplicidad, no he realizado validaciones


del parámetro de entrada. Asegúrate de validar todos los
parámetros de entrada en las aplicaciones que se ejecutan
en tu entorno de producción.

Consulta también
La receta Habilitar autorización para aplicaciones de la función en el capítulo 9,
Implementar prácticas recomendadas para Azure Functions

Almacenar datos del empleado mediante


enlaces de salida de tablas de Azure
Storage
En la receta anterior, has aprendido a crear un desencadenador de HTTP y a aceptar
los parámetros de entrada. Ahora trabajemos en algo interesante, es decir, donde
se almacenan los datos de entrada en un medio persistente. Azure Functions nos
permite almacenar datos de muchas maneras. Para este ejemplo, almacenaremos
los datos en el almacenamiento de tablas de Azure.

[8]
Capítulo 1

Preparación
En esta receta, descubrirás lo fácil que es integrar un desencadenador de HTTP
y el servicio almacenamiento de tablas de Azure usando enlaces de salida. La
función de desencadenador de HTTP de Azure recibe los datos de varias fuentes y
almacena los datos de perfil de usuario en una tabla de almacenamiento denominada
tblUserProfile. Vamos a seguir los requisitos previos que figuran a continuación:

• Para esta receta, usaremos el mismo desencadenador de HTTP que creamos


en nuestra receta anterior.
• Usaremos Explorador de Azure Storage, que es una herramienta que nos
ayuda a trabajar con los datos almacenados en la cuenta de Azure Storage.
La puedes descargar en http://storageexplorer.com/.
• Puedes obtener más información sobre cómo conectarte a la cuenta de
almacenamiento usando el Explorador de Azure Storage en https://docs.
microsoft.com/en-us/azure/vs-azure-tools-storage-manage-with-
storage-explorer.

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate a la pestaña Integrar de la función de desencadenador


de HTTP RegisterUser.
2. Haz clic en el botón Nueva salida, selecciona Almacenamiento de tablas
de Azure y, a continuación, haz clic en el botón Seleccionar:

[9]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

3. Se te pedirá que instales los enlaces y hagas clic en Instalar, lo que llevaría
unos minutos. Después de instalar los enlaces, selecciona la siguiente
configuración de los enlaces de salida de almacenamiento de tablas de Azure:
° Nombre de parámetro de tabla: es el nombre del parámetro que
usarás en el método de ejecución de la función de Azure.
Para este ejemplo, proporciona objUserProfileTable como valor.
° Nombre de tabla: se creará una nueva tabla en el almacenamiento
de tablas de Azure para conservar los datos. Si la tabla aún no existe,
¡Azure creará automáticamente una para ti! Para este ejemplo,
proporciona tblUserProfile como nombre de tabla.
° Conexión de la cuenta de almacenamiento: si no ves la cadena
Conexión de la cuenta de almacenamiento, haz clic en Nuevo
(como se muestra en la siguiente captura de pantalla) para crear
una nueva o seleccionar una cuenta de almacenamiento existente.
° Los enlaces de salida del almacenamiento de tablas de Azure
deben ser como se muestran en la siguiente captura de pantalla:

4. Haz clic en Guardar para guardar los cambios.


5. Desplázate hasta el editor de código haciendo clic en el nombre de la función
y pega el código siguiente. El código siguiente acepta la entrada pasada por
el usuario final y la guarda en el almacenamiento de tablas:
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Storage"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Microsoft.WindowsAzure.Storage.Table;
[ 10 ]
Capítulo 1

public static async Task<IActionResult> Run(


HttpRequest req,
CloudTable objUserProfileTable,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a
request.");
string firstname=null,lastname = null;
string requestBody = await new StreamReader(req.Body).
ReadToEndAsync();
dynamic inputJson = JsonConvert.DeserializeObject(requestBody);
firstname = firstname ?? inputJson?.firstname;
lastname = inputJson?.lastname;
UserProfile objUserProfile = new UserProfile(firstname,
lastname);
TableOperation objTblOperationInsert = TableOperation.
Insert(objUserProfile);
await objUserProfileTable.ExecuteAsync(objTblOperationInsert);
return (lastname + firstname) != null
? (ActionResult)new OkObjectResult($"Hello, {firstname + " " +
lastname}")
: new BadRequestObjectResult("Please pass a name on the query" +
"string or in the request body");
}

class UserProfile : TableEntity


{
public UserProfile(string firstName,string lastName)
{
this.PartitionKey = "p1";
this.RowKey = Guid.NewGuid().ToString();
this.FirstName = firstName;
this.LastName = lastName;
}
UserProfile() { }
public string FirstName { get; set; }
public string LastName { get; set; }
}

[ 11 ]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

6. Vamos a ejecutar la función haciendo clic en el botón Ejecutar de la pestaña


Prueba pasando los parámetros firstname y lastname en el Cuerpo
de la solicitud:

7. Si todo ha ido bien, deberías obtener un mensaje Estado 200 OK en el


cuadro Salida como se muestra en la captura de pantalla anterior. Vamos
a navegar hasta el explorador de Azure Storage y ver el almacenamiento
de tablas para comprobar si la tabla denominada tblUserProfile se ha
creado correctamente:

[ 12 ]
Capítulo 1

Cómo funciona...
Azure Functions nos permite integrar fácilmente con otros servicios de Azure
simplemente agregando un enlace de salida al desencadenador. Para este ejemplo,
hemos integrado el desencadenador de HTTP con el enlace de la tabla de Azure
Storage y también hemos configurado la cuenta de Azure Storage al proporcionar
la cadena de conexión de almacenamiento y el nombre de la tabla de Azure Storage
donde nos gustaría crear un registro para cada una de las solicitudes HTTP recibidas
por el desencadenador de HTTP.

También hemos agregado un parámetro adicional para controlar el almacenamiento


de tablas, denominado objUserProfileTable, del tipo CloudTable, al método Run.
Podemos realizar todas las operaciones en el almacenamiento de tablas
de Azure usando objUserProfileTable.

Los parámetros de entrada no se validan en el ejemplo


de código. Sin embargo, en tu entorno de producción, es
importante que los valides antes de almacenarlos en cualquier
tipo de medio persistente.

También hemos creado un objeto UserProfile y lo hemos rellenado con los


valores recibidos en el objeto de solicitud y, a continuación, lo hemos pasado
a una operación de tabla.

Puedes obtener más información acerca del control de operaciones


en el servicio de almacenamiento de tablas de Azure en https://
docs.microsoft.com/en-us/azure/storage/storage-
dotnet-how-to-use-tables.

[ 13 ]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

Comprender la conexión de almacenamiento


Al crear una nueva conexión de almacenamiento (consulta el paso 3 de la sección
Cómo hacerlo... de esta receta), se creará una nueva Configuración de la aplicación:

Puedes ir a Configuración de la aplicación haciendo clic en el menú Configuración


de la aplicación disponible en la sección CONFIGURACIÓN GENERAL de la
pestaña Características de la plataforma:

[ 14 ]
Capítulo 1

¿Qué es el servicio almacenamiento de tablas


de Azure?
El servicio de almacenamiento de tablas de Azure es un medio persistente
de pares de clave-valor NoSQL para almacenar datos semiestructurados.

Podrás obtener más información sobre este tema en https://


azure.microsoft.com/en-in/services/storage/tables/.

Clave de partición y clave de fila


La clave principal de la tabla de almacenamiento de Azure Table tiene dos partes:

• Clave de partición: los registros del almacenamiento de Azure Table se


clasifican y organizan en particiones. Cada registro ubicado en una partición
tendrá la misma clave de partición (p1 en nuestro ejemplo).
• Clave de fila: se debe asignar un valor único a cada una de las filas.

Y eso no es todo…
Las siguientes son las primeras líneas del código de esta receta:
#r "Newtonsoft.json"
#r "Microsoft.WindowsAzure.Storage"

Las líneas de código anteriores le indican a la función del runtime que incluya una
referencia de la biblioteca especificada al contexto actual.

Guardar las imágenes de perfil en colas


utilizando los enlaces de salida de cola
En la receta anterior, has aprendido a recibir dos parámetros de cadena, firstname
y lastname, en el Cuerpo de la solicitud y a almacenarlos en el almacenamiento de
tablas de Azure. En esta receta, vamos a agregar un parámetro nuevo denominado
ProfilePicUrl para la imagen de perfil del usuario al que se puede acceder
públicamente a través de Internet. En esta receta, descubrirás cómo recibir una
dirección URL de una imagen y guardarla en el contenedor de blobs de una cuenta
de Azure Storage.

[ 15 ]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

Podrías pensar que se podría haber usado el parámetro de entrada ProfilePicUrl


para descargar la imagen de Internet en la receta anterior, Almacenar datos del
empleado mediante enlaces de salida de tablas de Azure Storage. No lo hicimos porque el
tamaño de las imágenes de perfil podría ser enorme con la tecnología moderna y, por
lo tanto, el procesamiento de imágenes sobre la marcha en las solicitudes HTTP podría
dificultar el rendimiento de la aplicación en general. Por esa razón, solo tomaremos la
dirección URL de la imagen del perfil y la almacenaremos en la cola; luego, podremos
procesar la imagen y almacenarla en el blob.

Preparación
Actualizaremos el código de la función RegisterUser que usamos en las recetas
anteriores.

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate a la pestaña Integrar de la función de desencadenador


de HTTP RegisterUser.
2. Haz clic en el botón Nueva salida, selecciona Azure Queue Storage
y, a continuación, haz clic en el botón Seleccionar.
3. Proporciona los parámetros siguientes en la configuración de salida
de Azure Queue Storage:
° Nombre del parámetro de mensaje: define el nombre del parámetro
en objUserProfileQueueItem, que se usará en el método Run
° Nombre de cola: define el valor del nombre de cola como
userprofileimagesqueue
° Conexión de cuenta de almacenamiento: asegúrate de seleccionar
la cuenta de almacenamiento correcta en el campo Conexión de la
cuenta de almacenamiento
4. Haz clic en Guardar para crear el nuevo enlace de salida.
5. Vuelve al editor de código haciendo clic en el nombre de la función
(RegisterUser en este ejemplo) o el archivo run.csx y realiza los cambios
marcados en negrita en el código siguiente:
public static async Task<IActionResult> Run(
HttpRequest req,
CloudTable objUserProfileTable,
IAsyncCollector<string> objUserProfileQueueItem,
ILogger log)
{

....

[ 16 ]
Capítulo 1

string firstname= inputJson.firstname;


string profilePicUrl = inputJson.ProfilePicUrl;
await objUserProfileQueueItem.AddAsync(profilePicUrl);

....
objUserProfileTable.Execute(objTblOperationInsert);
}

6. En el código anterior, hemos agregado enlaces de salida de cola agregando


el parámetro IAsyncCollecter al método Ejecutar y simplemente pasando
el mensaje necesario al método AddAsync, los enlaces de salida se encargarán
de guardar ProfilePicUrl en la cola. Ahora, haz clic en Guardar para
guardar los cambios de código en el editor de código del archivo run.csx.
7. Vamos a probar el código agregando otro parámetro, ProfilePicUrl, al
Cuerpo de la solicitud y haciendo clic en el botón Ejecutar en la pestaña
Prueba de la ventana del editor de código de la función de Azure. Es posible
que la imagen utilizada en el siguiente JSON no exista al leer este libro. Por lo
tanto, asegúrate de proporcionar una dirección URL válida de la imagen:
{
"firstname": "Bill",
"lastname": "Gates",
"ProfilePicUrl":"https://upload.wikimedia.org/wikipedia/
commons/1/19/Bill_Gates_June_2015.jpg"
}

8. Si todo va bien, verás el mensaje Estado: 200 OK; luego, la dirección URL
de la imagen que has pasado como un parámetro de entrada en el cuerpo
de la solicitud se creará como un mensaje de cola en el servicio de cola de
Azure Storage. Vamos a ir al explorador de Azure Storage y ver la cola
denominada userprofileimagesqueue, que es el nombre de cola que hemos
proporcionado en el paso 3. La siguiente es una captura de pantalla del
mensaje de cola que se creó:

[ 17 ]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

Cómo funciona...
En esta receta, hemos agregado el enlace de salida del mensaje de cola y hemos
hecho los cambios siguientes al código:

• Hemos agregado un parámetro nuevo denominado out string


objUserProfileQueueItem, que se usa para enlazar la dirección URL
de la imagen de perfil como contenido del mensaje de cola
• Hemos usado el método AddAsync de IAsyncCollector en el método Run,
que guarda la dirección URL de perfil para la cola como un mensaje de cola.

Almacenar la imagen en Azure Blob


Storage
En la receta anterior, almacenamos la dirección URL de la imagen en el mensaje
de cola. Descubramos cómo activar una función de Azure (desencadenador de cola)
cuando se agrega un nuevo elemento de cola al servicio de cola de Azure Storage.
Cada mensaje de la cola es la dirección URL de la imagen de perfil de un usuario,
que Azure Functions procesará y se almacenará como un blob en el servicio Azure
Storage Blob.

Preparación
En la receta anterior, aprendimos a crear enlaces de salida de cola. En esta receta,
tomarás la dirección URL de la cola, crearás una matriz de bytes y luego la escribirás
en un blob.

Esta receta es una continuación de las recetas anteriores. Asegúrate de que las has
implementado.

Cómo hacerlo...
Sigue estos pasos:

1. Crea una nueva función de Azure seleccionando Desencadenador de Azure


Queue Storage en las plantillas.
2. Proporciona los siguientes detalles después de elegir la plantilla:
° Asigna un nombre a la función: proporciona un nombre descriptivo,
como CreateProfilePictures.

[ 18 ]
Capítulo 1

° Nombre de cola: nombre de la cola userprofileimagesqueue. Esto


se supervisará mediante la función de Azure. Nuestra receta anterior
creó un nuevo elemento para cada una de las solicitudes válidas que
llegan al desencadenador de HTTP (denominado RegisterUser) en
la cola userprofileimagesqueue. Para cada nueva entrada de un
mensaje de cola a este almacenamiento de cola, el desencadenador
CreateProfilePictures se ejecutará automáticamente.
° Conexión de cuenta de almacenamiento: conexión de la cuenta
de almacenamiento donde se encuentran las colas.
3. Revisa todos los detalles, haz clic en Crear para crear la nueva función.
4. Desplázate hasta la pestaña Integrar, haz clic en Nueva salida, selecciona
Azure Blob Storage y, a continuación, haz clic en el botón Seleccionar.
5. En la sección Salida de Azure Blob Storage, proporciona lo siguiente:
° Nombre del parámetro blob: defínelo en outputBlob
° Ruta: defínela en userprofileimagecontainer/{rand-guid}
° Conexión de la cuenta de almacenamiento: selecciona la cuenta de
almacenamiento en la que te gustaría guardar los blobs y haz clic en
el botón Guardar:

6. Haz clic en el botón Guardar para guardar todos los cambios.


7. Sustituye el código predeterminado del archivo run.csx de la función
CreateProfilePictures por el código siguiente. El siguiente código toma la
dirección URL de la cola, crea una matriz de bytes y luego la escribe en un blob:
using System;
public static void Run(Stream outputBlob,string
myQueueItem,
TraceWriter log)
{
byte[] imageData = null;
using (var wc = new System.Net.WebClient())

[ 19 ]
Desarrollar aplicaciones en el cloud mediante desencadenadores y enlaces de funciones

{
imageData = wc.DownloadData(myQueueItem);
}
outputBlob.WriteAsync(imageData,0,imageData.Length);
}

8. Haz clic en el botón Guardar para guardar los cambios. Asegúrate de que
no haya errores de compilación en la ventana Registros:

9. Volvamos a la función RegisterUser y probémosla proporcionando los


campos firstname, lastname y ProfilePicUrl como lo hicimos en la receta
Guardar las imágenes de perfil en colas utilizando los enlaces de salida de cola.
10. Desplázate hasta el explorador de Azure Storage y busca el contenedor
de blobs userprofileimagecontainer. Encontrarás un blob nuevo:

11. Puedes ver la imagen en cualquier herramienta (como MS Paint


o Internet Explorer).

Cómo funciona...
Hemos creado un desencadenador de cola que se ejecuta cuando llega un nuevo
mensaje a la cola. Cuando encuentra un nuevo mensaje de cola, lo lee; como
sabemos, el mensaje es una dirección URL de una imagen de perfil. La función
realiza una solicitud de cliente web, descarga los datos de imagen en forma de matriz
de bytes y luego escribe los datos en el blob, que está configurado como un blob
de salida.

[ 20 ]
Capítulo 1

Y eso no es todo…
El parámetro rand-guid generará un GUID nuevo asignado al blob que se crea
cada vez que se activa el desencadenador.

Es obligatorio especificar el nombre del contenedor de blobs en el


parámetro Ruta del enlace de salida de almacenamiento de blobs
mientras se configura la salida de almacenamiento de blobs. Azure
Functions crea uno automáticamente si no existe.
Puedes usar los mensajes de cola solo cuando desees almacenar mensajes
de hasta 64 KB. Si deseas almacenar mensajes de más de 64 KB, debes
usar Azure Service Bus.

[ 21 ]
Trabajar con notificaciones
mediante los servicios
SendGrid y Twilio
En este capítulo, veremos lo siguiente:

• Enviar una notificación por correo electrónico al administrador de un sitio


web mediante el servicio SendGrid
• Enviar una notificación de correo electrónico dinámicamente al usuario final
• Implementar el registro de correo electrónico en Azure Blob Storage
• Modificar el contenido del correo electrónico para incluir un archivo adjunto
• Enviar una notificación por SMS al usuario final utilizando el servicio Twilio

Introducción
Para que cada aplicación empresarial ejecute sus operaciones comerciales sin
problemas, una de las características clave es tener un sistema de comunicación fiable
entre la empresa y sus clientes. El canal de comunicación puede ser bidireccional,
ya sea enviando un mensaje a los administradores que gestionan la aplicación o
enviando alertas a los clientes por correo electrónico o SMS a sus teléfonos móviles.

Azure puede integrarse con dos servicios de comunicación populares: SendGrid para
correos electrónicos y Twilio para trabajar con SMS. En este capítulo, usaremos estos
dos servicios de comunicación para descubrir cómo aprovechar sus servicios básicos
para enviar mensajes entre los administradores empresariales y los usuarios finales.

[ 23 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

A continuación, se muestra la arquitectura que usaremos para utilizar los enlaces


de salida de SendGrid y Twilio con el desencadenador de HTTP y el desencadenador
de cola.

Enviar una notificación por correo


electrónico al administrador de un sitio
web mediante el servicio SendGrid
En esta receta, descubrirás cómo crear un enlace de salida de SendGrid y enviar
una notificación por correo electrónico, con contenido estático, al administrador
del sitio web. Nuestro caso de uso solo involucra a un administrador, por lo que
codificaremos la dirección de correo electrónico del administrador en el campo
Destinatario del enlace de salida (mensaje) de SendGrid.

Preparación
Seguiremos estos pasos antes de continuar:

1. Crear una clave de API de la cuenta de SendGrid desde el portal


de administración de Azure
2. Generar una clave de API desde el portal de SendGrid
3. Configurar la clave de API de SendGrid con la aplicación Azure Function

Creación de una cuenta de SendGrid


Sigue estos pasos:

1. Desplázate al portal de administración de Azure y crea una cuenta


de Entrega de correo electrónico de SendGrid buscándola en el marketplace,
como se muestra en la siguiente captura de pantalla:
[ 24 ]
Capítulo 2

2. En la hoja Entrega de correo electrónico de SendGrid, haz clic en el botón


Crear para ir a Crear una nueva cuenta de SendGrid. Selecciona gratis en
las opciones de Nivel de precios, proporciona todos los demás detalles y,
a continuación, haz clic en el botón Crear, como se muestra en la siguiente
captura de pantalla:

[ 25 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

En el momento de la redacción, la cuenta gratuita de SendGrid


nos permite enviar 25 000 correos electrónicos gratuitos al mes.
Si deseas enviar más correos electrónicos, puedes obtener una
cuenta de nivel Silver S2, donde dispondrías de 100 000 correos
electrónicos al mes.

3. Una vez creada la cuenta correctamente, desplázate hasta Cuentas de


SendGrid. Puedes usar el cuadro de búsqueda disponible en la parte
superior, como se muestra en la siguiente captura de pantalla:

4. Ve a Configuración, selecciona Configuraciones y recupera USERNAME


y SMTP SERVER de la hoja Configuraciones, como se muestra en la
siguiente captura de pantalla:

[ 26 ]
Capítulo 2

Generar una clave de API desde el portal de SendGrid


Sigue estos pasos:

1. Para poder utilizar la cuenta de SendGrid en el runtime de Azure Functions,


debemos proporcionar la clave de API de SendGrid como una entrada
de Azure Functions. Puedes generar una clave de API desde el portal
de SendGrid. Vayamos al portal de SendGrid haciendo clic en el botón
Administrar en la hoja Essentials de la cuenta de SendGrid, como se
muestra en la siguiente captura de pantalla:

2. En el portal de SendGrid, haz clic en Claves de API en la sección


Configuración del menú del lado izquierdo, como se muestra en la
siguiente captura de pantalla:

3. En la página Claves de API, haz clic en Crear clave de API, como se


muestra en la siguiente captura de pantalla:

[ 27 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

4. En la ventana emergente Crear clave de API, proporciona un nombre


y selecciona Permisos de clave de API y, a continuación, haz clic en el botón
Crear y ver.
5. Al cabo de unos momentos, podrás ver la clave de API. Haz clic en la clave
para copiarla en el portapapeles, como se muestra en la siguiente captura
de pantalla:

Configurar la clave de API de SendGrid con la


aplicación Azure Function
Sigue estos pasos:

1. Crea una nueva Configuración de la aplicación en la aplicación Azure


Function desplazándote hasta la hoja Configuración de la aplicación, que
se encuentra en la sección Características de la plataforma de la aplicación
de función, como se muestra en la siguiente captura de pantalla:

2. Haz clic en el botón Guardar después de añadir la configuración de la


aplicación en el paso anterior.

Cómo hacerlo...
En esta sección, seguiremos estos pasos.

1. Crear un enlace de la cola de almacenamiento al desencadenador de HTTP


2. Crear un desencadenador de cola para procesar el mensaje del
desencadenador de HTTP
3. Crear un enlace de salida de SendGrid al desencadenador de cola
4. Crear un enlace de salida de Twilio al desencadenador de cola
[ 28 ]
Capítulo 2

Crear un enlace de la cola de almacenamiento


al desencadenador de HTTP
Sigue estos pasos:

1. Ve a la pestaña Integrar de la función RegisterUser y haz clic en el botón


Nueva salida para añadir un nuevo enlace de salida.
2. Selecciona Azure Queue Storage y haz clic en el botón Seleccionar para
añadir el enlace y proporcionar los valores que se muestran a continuación;
luego, haz clic en el botón Guardar. Escribe el nombre de la cola (en este
caso, notificationqueue) que se usará en un momento.

3. Desplázate hasta el método Run de la función RegisterUser y realiza los


siguientes cambios resaltados. Hemos añadido otro enlace de salida de
cola y un mensaje de salida para desencadenar la función Desencadenador
de cola. Por el momento, no hemos añadido ningún mensaje a la cola.
Realizaremos cambios al método NotificationQueueItem.AddAsync("");
en la próxima receta del capítulo.
public static async Task<IActionResult> Run(
HttpRequest req,
CloudTable objUserProfileTable,
IAsyncCollector<string> objUserProfileQueueItem,
IAsyncCollector<string> NotificationQueueItem,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a
request.");
string firstname=null,lastname = null;
...
...
await NotificationQueueItem.AddAsync("");
return (lastname + firstname) != null
? (ActionResult)new OkObjectResult($"Hello, {firstname + "
" + lastname}")
: new BadRequestObjectResult("Please pass a name on the
[ 29 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

query" +
"string or in the request body");
}

Crear un desencadenador de cola para procesar


el mensaje del desencadenador de HTTP
1. Crea un desencadenador de Azure Queue Storage seleccionando la plantilla
que se muestra a continuación.

2. En el paso siguiente, proporciona todo el nombre del desencadenador de


cola y escribe el nombre de la cola que se debe supervisar para enviar las
notificaciones. Después de proporcionar todos los detalles, haz clic en el
botón Crear para crear la función.

[ 30 ]
Capítulo 2

3. Después de crear la función Desencadenador de cola, vamos a ejecutar la


función RegisterUser para ver si se invoca el desencadenador de cola. Abre
la función RegisterUser en una pestaña nueva y pruébala haciendo clic en
el botón Ejecutar. En la ventana Registros de la pestaña SendNotifications,
deberías ver algo parecido a lo que se muestra a continuación:

Después de asegurarnos que el desencadenador de cola funciona como se esperaba,


vamos a crear los enlaces de SendGrid para enviar el correo electrónico.

Crear un enlace de salida de SendGrid al


desencadenador de cola
1. Ve a la pestaña Integrar de la función SendNotifications y haz clic en el botón
Nueva salida para añadir un nuevo enlace de salida.
2. Selecciona el enlace de SendGrid y haz clic en el botón Seleccionar para
añadir el enlace.
3. El siguiente paso es instalar las extensiones de SendGrid. Haz clic en el
botón Instalar para instalar las extensiones. La instalación de las extensiones
puede tardar unos minutos.
4. Proporciona los siguientes parámetros en el enlace de salida (mensaje)
de SendGrid:

° Nombre del parámetro del mensaje: deja el valor predeterminado,


que es message. Utilizaremos este parámetro en el método Run en
unos momentos.
° Clave de API de SendGrid: selecciona la clave de Configuración
de la aplicación que has creado en Configuración de la aplicación
para almacenar la clave de API de SendGrid.
° Destinatario: escribe la dirección de correo electrónico del
administrador.
° Remitente: escribe la dirección de correo electrónico desde
la que deseas enviar el mensaje. Puede ser parecida a
donotreply@example.com.

[ 31 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

° Asunto del mensaje: proporciona el asunto que deseas que se


muestre en el asunto del correo electrónico.
° Texto del mensaje: proporciona el cuerpo del correo electrónico
que deseas en el cuerpo del correo electrónico.

5. A continuación, podemos ver el aspecto del enlace de salida (mensaje)


de SendGrid después de rellenar todos los campos:

6. Después de revisar los valores, haz clic en Guardar para guardar los cambios.
7. Desplázate hasta el método Run de las funciones SendNotifications y
realiza los siguientes cambios:
° Agrega una referencia nueva para SendGrid, junto con el espacio
de nombres SendGrid.Helpers.Mail.
° Agrega un nuevo mensaje de parámetro del tipo SendGridMessage.
° Crea un objeto del tipo SendGridMessage. Vamos a ver cómo utilizar
este objeto en la siguiente receta.

8. A continuación, vemos el código completo del método Run:


#r "SendGrid"
using System;
using SendGrid.Helpers.Mail;

public static void Run(string myQueueItem,out SendGridMessage


message, ILogger log)
{
log.LogInformation($"C# Queue trigger function processed:

[ 32 ]
Capítulo 2

{myQueueItem}");
message = new SendGridMessage();
}

9. Ahora, vamos a probar la funcionalidad de envío del correo electrónico


yendo a la función RegisterUser y enviando una solicitud con algunos
valores de prueba, de la siguiente manera:
{
"firstname": "Bill",
"lastname": "Gates",
"ProfilePicUrl":"https://upload.wikimedia.org/
wikipedia/commons/thumb/1/19/
Bill_Gates_June_2015.jpg/220px-
Bill_Gates_June_2015.jpg"
}

Cómo funciona...
El objetivo de esta receta es enviar una notificación por correo electrónico al
administrador, enviándoles una actualización para informarle de que se ha creado
un registro nuevo.

Hemos usado uno de los enlaces de salida de Azure Function, denominado


SendGrid, como un servidor Protocolo simple de transferencia de correo (SMTP)
para enviar nuestros correos electrónicos codificando las propiedades siguientes en
los enlaces de salida (mensaje) de SendGrid:

• El "remitente" del correo electrónico


• El "destinatario" del correo electrónico
• El asunto del correo electrónico
• El cuerpo del correo electrónico

Los enlaces de salida (mensaje) de SendGrid utilizarán la clave de API


proporcionada en Configuración de la aplicación para invocar las API necesarias
de la biblioteca SendGrid para enviar los correos electrónicos.

[ 33 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

Y eso no es todo
Al agregar los enlaces de SendGrid, se te solicitará que instales las extensiones como
se muestra a continuación.

Si no las puedes ver, elimina el enlace de salida y vuelve a crearlas. También puedes
instalar manualmente las extensiones si sigues las instrucciones que se mencionan
en el artículo https://docs.microsoft.com/azure/azure-functions/install-
update-binding-extensions-manual.

Enviar una notificación de correo


electrónico dinámicamente
al usuario final
En la receta anterior, hemos codificado la mayoría de los atributos relacionados
con el envío de un correo electrónico a un administrador, ya que solo había un
administrador. En esta receta, modificaremos la receta anterior para enviar un
correo electrónico de agradecimiento por inscribirse a los propios usuarios.

Preparación
Asegúrate de que lo siguiente está configurado correctamente:

• Se ha creado la cuenta de SendGrid y se ha generado una clave de API


en el portal de SendGrid.
• Se ha creado la Configuración de la aplicación en la Configuración
de la aplicación de la aplicación de la función.
• La clave de Configuración de la aplicación se ha configurado en los enl
aces de salida (mensaje) de SendGrid.

[ 34 ]
Capítulo 2

Cómo hacerlo...
En esta receta, actualizaremos el código en el archivo run.csx de las siguientes
Azure Functions
• RegisterUser
• SendNotifications

Aceptar el nuevo parámetro de correo electrónico


en la función RegisterUser
Sigue estos pasos:

1. Ve a la función RegisterUser, que se encuentra en el archivo run.csx,


agrega una nueva variable de cadena que acepte un nuevo parámetro de
entrada, denominada email, desde el objeto de solicitud, de la forma
siguiente. Además, ten en cuenta que estamos serializando el objeto
UserProfile y almacenando el contenido JSON en el mensaje de cola:
string firstname=null,lastname = null, email = null;
...
...
string email = inputJson.email;
...
...
UserProfile objUserProfile = new UserProfile(firstname,
lastname,email);
...
...
await
NotificationQueueItem.AddAsync(JsonConvert.SerializeObject(objUser
Profile));

2. Actualiza el siguiente código resaltado de la clase UserProfile y haz clic en


el botón Guardar para guardar los cambios:
public class UserProfile : TableEntity
{
public UserProfile(string firstname,string lastname,
string profilePicUrl,string email)
{
....
....
this.ProfilePicUrl = profilePicUrl;
this.Email = email;
}
....
....
public string ProfilePicUrl {get; set;}
[ 35 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

public string Email { get; set; }


}

Recuperar la información de UserProfile en el


desencadenador SendNotifications
Sigue estos pasos

1. Desplázate hasta la función SendNotifications, en el archivo run.csx,


agrega la referencia NewtonSoft.Json y también el espacio de nombres.
2. El desencadenador de cola recibirá la entrada en forma de cadena JSON.
Utilizaremos el método JsonConvert.DeserializeObject para convertir la
cadena en un objeto dinámico para que podamos recuperar las propiedades
individuales. Reemplaza el código existente por el código siguiente donde
se rellenan dinámicamente las propiedades de SendGridMessage desde
el código.
#r "SendGrid"
#r "Newtonsoft.Json"
using System;
using SendGrid.Helpers.Mail;
using Newtonsoft.Json;

public static void Run(string myQueueItem,


out SendGridMessage message,
ILogger log)
{
log.LogInformation($"C# Queue trigger function processed:
{myQueueItem}");
dynamic inputJson = JsonConvert.DeserializeObject(myQueueItem);
string FirstName=null, LastName=null, Email = null;
FirstName=inputJson.FirstName;
LastName=inputJson.LastName;
Email=inputJson.Email;
log.LogInformation($"Email{inputJson.Email}, {inputJson.FirstName
+ " " + inputJson.LastName}");
message = new SendGridMessage();
message.SetSubject("New User got registered successfully.");
message.SetFrom("donotreply@example.com");
message.AddTo(Email,FirstName + " " + LastName);
message.AddContent("text/html", "Thank you " + FirstName + " " +
LastName +" so much for getting registered to our site.");
}

[ 36 ]
Capítulo 2

3. Vamos a ejecutar una prueba agregando un nuevo correo electrónico


de campo de entrada a la carga de la solicitud de pruebas, que se muestra
de la siguiente manera:
{
"firstname": "Praveen",
"lastname": "Sreeram",
"email":"example@gmail.com",
"ProfilePicUrl":"A Valid url here"
}

4. Esta es la captura de pantalla del correo electrónico que he recibido:

Cómo funciona...
Hemos actualizado el código de la función RegisterUser para aceptar otro
parámetro nuevo, denominado email.

La función acepta el parámetro email y envía el correo al usuario final mediante la


API de SendGrid. También hemos configurado todos los demás parámetros, como
el Remitente, el Asunto y el cuerpo (contenido) del código, para que se personalice
dinámicamente en función de los requisitos.

[ 37 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

También podemos borrar los campos de los enlaces de salida de SendGrid, como
se muestra en la siguiente captura de pantalla:

Los valores especificados en el código tendrán prioridad


sobre los otros valores especificados en el paso anterior.

Y eso no es todo…
También puedes enviar contenido HTML en el cuerpo para que el correo electrónico
sea más atractivo. El siguiente es un ejemplo sencillo, en el que acabo de aplicar una
etiqueta de negrita (<b>) al nombre de usuario final:
message.AddContent("text/html", "Thank you <b>" + FirstName + "</b><b>
" + LastName +" </b>so much for getting registered to our site.");

La siguiente es la captura de pantalla del correo electrónico, con mi nombre


en negrita:

[ 38 ]
Capítulo 2

Implementar el registro de correo


electrónico en Azure Blob Storage
La mayoría de las aplicaciones empresariales de los correos electrónicos
automatizados probablemente impliquen el envío de correos electrónicos que
contengan notificaciones, alertas, etc., al usuario final. A veces, los usuarios pueden
quejarse de que no han recibido ningún correo electrónico, aunque no vemos ningún
error en la aplicación al enviar dichas alertas de notificación.
Puede haber varias razones por las que los usuarios no han recibido el correo
electrónico. Cada uno de los proveedores de servicios de correo electrónico tiene
diferentes filtros de correo no deseado que pueden bloquear los correos electrónicos
de la bandeja de entrada del usuario final. Pero estos correos electrónicos pueden
tener información importante que los usuarios pueden necesitar. Tiene sentido
almacenar el contenido de todos los correos electrónicos que se envían a los usuarios
finales para que podamos recuperar los datos en un paso posterior para solucionar
problemas imprevistos.
En esta receta, aprenderás a crear un nuevo archivo de registro de correo electrónico
con la extensión .log para cada nuevo registro. Este archivo de registro se puede
utilizar como redundancia para los datos almacenados en el almacenamiento de
tablas. También aprenderás a almacenar los archivos de registro de correo electrónico
como un blob en un contenedor de almacenamiento, junto con los datos introducidos
por el usuario final durante el registro.

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate hasta la pestaña Integrar de la función SendNotifications,


haz clic en Nueva salida y selecciona Azure Blob Storage. Se te pedirá que
instales las extensiones de almacenamiento; instálalas para continuar.
2. Proporciona los parámetros necesarios en la sección de salida Azure Blob
Storage, como se muestra en la siguiente captura de pantalla. Ten en cuenta
la extensión .log en el campo Ruta:

[ 39 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

3. Ve al editor de código del archivo run.csx de la función


SendNotifications y realiza los siguientes cambios:
1. Añade un nuevo parámetro outputBlob del tipo TextWriter al
método Run.
2. Añade una nueva variable de cadena denominada emailContent.
Esta variable se utiliza para enmarcar el contenido del correo
electrónico. También utilizaremos la misma variable para crear el
contenido del archivo de registro que se almacena en el blob.
3. Enmarca el contenido del correo electrónico anexando el texto
estático necesario y los parámetros de entrada recibidos en Cuerpo
de la solicitud, como se indica a continuación:
public static void Run(string myQueueItem,
out SendGridMessage message,
TextWriter outputBlob,
ILogger log)
....
....
string FirstName=null, LastName=null, Email = null;
string emailContent;
....
....
emailContent = "Thank you <b>" + FirstName + " " +
LastName +"</b> for your registration.<br><br>" +
"Below are the details that you have provided
us<br> <br>"+ "<b>First name:</b> " +
FirstName + "<br>" + "<b>Last name:</b> " +
LastName + "<br>" + "<b>Email Address:</b> " +
inputJson.Email + "<br><br> <br>" + "Best Regards," +
"<br>" + "Website Team";
message.AddContent(new
Content("text/html",emailContent));
outputBlob.WriteLine(emailContent);

4. Ejecuta una prueba con la misma carga de solicitud que usamos en la receta
anterior.
5. Después de ejecutar la prueba, el archivo de registro se creará en el
contenedor denominado userregistrationemaillogs:

[ 40 ]
Capítulo 2

Cómo funciona...
Hemos creado nuevos enlaces de salida de Azure Blob. Tan pronto como se recibe
una nueva solicitud, el contenido del correo electrónico se crea y se escribe en
un nuevo archivo .log (ten en cuenta que también puedes usar cualquier otra
extensión) que se almacena como un blob en el contenedor especificado en el
campo Ruta de los enlaces de salida.

Modificar el contenido del correo


electrónico para incluir un archivo
adjunto
En esta receta, aprenderás a enviar un archivo como un adjunto al usuario registrado.
En la receta anterior, creamos un archivo de registro del contenido de correo
electrónico. Enviaremos el mismo archivo como un adjunto al correo electrónico.
Sin embargo, en las aplicaciones del mundo real, podrías no desear enviar archivos
de registro al usuario final. Para simplificar la tarea, enviaremos el archivo de
registro como un archivo adjunto.

En el momento de escribir, SendGrid recomienda que el


tamaño del archivo adjunto no exceda los 10 MB, aunque,
técnicamente, el correo electrónico puede llegar a ser de 20 MB.

[ 41 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

Preparación
Esta receta es una continuación de la receta anterior. Si estás leyendo esto primero,
asegúrate de repasar previamente las recetas de este capítulo.

Cómo hacerlo...
Tendremos que seguir estos pasos antes de continuar:

1. Realizar los cambios en el código para crear un archivo de registro con


RowKey de la tabla. Lo lograremos usando la interfaz IBinder.
2. Enviar este archivo como un archivo adjunto al correo electrónico.

Personalizar el nombre del archivo de registro


utilizando la interfaz IBinder
Sigue estos pasos:

1. Ve hasta el archivo run.csx de la función SendNotifications.


2. Borra el objeto TextWriter y sustitúyelo por el enlazador de variables del
tipo IBinder. A continuación, se muestra la nueva firma del método Run con
los cambios resaltados:
#r "SendGrid"
#r "Newtonsoft.Json"
#r "Microsoft.Azure.WebJobs.Extensions.Storage"
using System;
using SendGrid.Helpers.Mail;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs.Extensions.Storage;
public static void Run(string myQueueItem,
out SendGridMessage message,
IBinder binder,
ILogger log)

3. Hemos eliminado el objeto TextWriter y la función outputBlob.


WriteLine(emailContent); dejará de funcionar. Vamos a sustituirla por
el siguiente fragmento de código:
using (var emailLogBloboutput = binder.
Bind<TextWriter>(new
BlobAttribute($"userregistrationemaillogs/
{objInsertedUser.RowKey}.log")))
{
emailLogBloboutput.WriteLine(emailContent);
}

[ 42 ]
Capítulo 2

4. Ejecutemos una prueba con la misma carga de solicitud que usamos


en las recetas anteriores.
5. Puedes ver el archivo de registro de correo electrónico que se crea con la
RowKey del nuevo registro almacenado en el almacenamiento de tablas
de Azure, como se muestra en la siguiente captura de pantalla:

Agregar un archivo adjunto al correo electrónico


Sigue estos pasos:

1. Agrega el siguiente código al método Run de la función SendNotifications


y guarda los cambios haciendo clic en el botón Guardar:
message.AddAttachment(FirstName +"_"+LastName+".log",
System.Convert.
ToBase64String(System.Text.Encoding.UTF8.GetBytes(emailContent)),
"text/plain",
"attachment",
"Logs"
);

2. Ejecuta una prueba usando la misma carga de solicitud que hemos usado en
las recetas anteriores.

[ 43 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

3. Esta es la captura de pantalla del correo electrónico, junto con el archivo


adjunto:

Puedes obtener más información sobre la API de SendGrid en


https://sendgrid.com/docs/API_Reference/api_v3.html

Enviar una notificación por SMS al


usuario final utilizando el servicio Twilio
En la mayoría de las recetas anteriores de este capítulo, hemos trabajado con
desencadenadores SendGrid para enviar correos electrónicos en diferentes
escenarios. En esta receta, aprenderás a enviar notificaciones a través de SMS,
utilizando Twilio, una de las plataformas de comunicación en el cloud líderes
en el sector.

También puedes obtener más información


acerca de Twilio en
https://www.twilio.com/.

[ 44 ]
Capítulo 2

Preparación
Par poder usar el enlace Twilio SMS output (objsmsmessage), tenemos que hacer
lo siguiente:

1. Crear una cuenta de prueba de Twilio en https://www.twilio.com/try-


twilio.
2. Después de haber creado la cuenta correctamente, toma ACCOUNT SID
y AUTH TOKEN del panel de Twilio, como se muestra en la siguiente
captura de pantalla. Crearemos dos configuraciones de la aplicación en la
hoja Configuración de la aplicación de la aplicación de función para dos
de estas configuraciones:

3. Para empezar a enviar mensajes, debes crear un número activo en Twilio,


que se utilizará como número remitente para enviar el SMS. Puedes crear
y administrar números en el panel de números de teléfono. Desplázate
hasta https://www.twilio.com/console/phone-numbers/incoming y haz
clic en el botón Primeros pasos, como se muestra en la siguiente captura
de pantalla:

[ 45 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

4. En la página Primeros pasos con números de teléfono, haz clic en Obtén tu


primer número de teléfono Twilio, como se muestra en la siguiente captura
de pantalla:

5. Después de obtenerlo, se enumerará de la siguiente manera:

6. El último paso es verificar un número al que te gustaría enviar un SMS. Solo


puedes tener un número en la cuenta de prueba. Puedes verificar un número
en la página Verified de Twilio, disponible en https://www.twilio.com/
console/phone-numbers/verified. A continuación, vemos una captura
de pantalla de la lista de números verificados:

[ 46 ]
Capítulo 2

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate hasta la hoja Configuración de la aplicación de la aplicación


de función y agrega dos claves para almacenar TwilioAccountSID
y TwilioAuthToken, como se muestra a continuación:

2. Ve a la pestaña Integrar de la función SendNotifications, haz clic en Nueva


salida y selecciona Twilio SMS.
3. Haz clic en Seleccionar y proporciona los valores siguientes a los enlaces
de salida de Twilio SMS. Instala las extensiones de Twilio. El número
remitente es el número que se ha generado en el portal de Twilio y del que
ya hemos hablado en la sección Preparación de esta receta:

4. Ve al editor de código y agrega las siguientes líneas de código, resaltadas


en negrita. En el código siguiente, he codificado el número destinatario. Sin
embargo, en escenarios del mundo real, recibirás dinámicamente el número
de móvil del usuario final y enviarás el SMS a través del código:
...
...
#r "Twilio"
#r "Microsoft.Azure.WebJobs.Extensions.Twilio"
...
...
using Microsoft.Azure.WebJobs.Extensions.Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

[ 47 ]
Trabajar con notificaciones mediante los servicios SendGrid y Twilio

public static void Run(string myQueueItem,


out SendGridMessage message,
IBinder binder,
out CreateMessageOptions objsmsmessage,
ILogger log)
...
...
...
message.AddAttachment(FirstName +"_"+LastName+".log",
System.Convert.ToBase64String(System.Text.Encoding.UTF8.
GetBytes(emailContent)),
"text/plain",
"attachment",
"Logs"
);

objsmsmessage = new CreateMessageOptions(new


PhoneNumber("+91 98492*****"));
objsmsmessage.Body = "Hello.. Thank you for getting
registered.";
}

5. Ahora, hagamos una ejecución de prueba de la función RegisterUser


utilizando la misma carga de solicitud.
6. A continuación, vemos la captura de pantalla del SMS que he recibido:

[ 48 ]
Capítulo 2

Cómo funciona...
Hemos creado una nueva cuenta de Twilio y hemos copiado el ID de cuenta
y la clave de aplicación en Configuración de la aplicación de la aplicación Azure
Function. El runtime de la aplicación de función utilizará estas dos configuraciones
para conectarse a la API de Twilio para enviar el SMS.

Para simplificar la tarea, he codificado el número de teléfono en los enlaces de salida.


Sin embargo, en las aplicaciones del mundo real, el SMS se enviaría al número de
teléfono proporcionado por los usuarios finales.

Puedes visionar el vídeo https://www.youtube.com/watch?v=ndxQXnoDIj8 para


ver una implementación que funcione.

[ 49 ]
Integración perfecta de Azure
Functions con los Servicios
de Azure
En este capítulo, abordaremos las siguientes recetas:

• Usar Cognitive Services para identificar caras en imágenes


• Interacciones de Azure SQL Database mediante Azure Functions
• Supervisar tweets a través de Logic Apps y notificar a los usuarios
publicaciones de tweets de usuarios populares
• Integrar Logic Apps con funciones sin servidor
• Auditorías de datos de Cosmos DB mediante desencadenadores de fuente
de cambios

Introducción
Uno de los principales objetivos de Azure Functions es permitir que los
desarrolladores puedan centrarse exclusivamente en el desarrollo de requisitos
de aplicaciones y lógica, y resumir todo lo demás.

Como desarrollador o usuario profesional, no dispones de los medios para inventar


y desarrollar tus propias aplicaciones desde cero para cada una de tus necesidades
empresariales. Primero tendrías que investigar los sistemas existentes y determinar
si se ajustan a los requisitos de tu negocio. En muchas ocasiones, no resultaría
sencillo comprender las API de otros sistemas e integrarlas, ya que las habría
desarrollado otra persona.

[ 51 ]
Integración perfecta de Azure Functions con los Servicios de Azure

Azure proporciona muchos conectores que puedes aprovechar para integrar tus
aplicaciones empresariales con otros sistemas de manera muy sencilla.

En este capítulo, descubriremos lo fácil que es integrar los diferentes servicios


que hay disponibles en el ecosistema de Azure.

Usar Cognitive Services para identificar


caras en imágenes
En esta receta, aprenderás a usar la Computer Vision API para detectar caras
dentro de una imagen, de tal modo que localizaremos las caras y capturaremos sus
coordenadas, y las guardaremos en diferentes áreas de Almacenamiento de tablas
de Azure en función del género.

Preparación
Para empezar, es necesario crear una Computer Vision API y configurar las claves
de API para que Azure Functions (o cualquier otro programa) pueda tener acceso
a ella mediante programación.

Debes asegurarte de que está instalado el explorador de Azure Storage y de que este
se ha configurado para obtener acceso al área de almacenamiento donde vas a cargar
los blobs.

Crear una nueva cuenta de Computer Vision API


Sigue estos pasos:

1. Busca Computer Vision y haz clic en Crear.


2. El siguiente paso es proporcionar todos los detalles para crear una cuenta
de Computer Vision API. En el momento en que se redactó esta receta, la
API de Computer Vision solo ofrece dos niveles de precios. Mi elección fue
la opción gratuita, F0, que permite 20 llamadas a API por minuto y tiene un
límite de 5000 llamadas al mes.

[ 52 ]
Capítulo 3

Ajustar la configuración de la aplicación


Sigue estos pasos:

1. Una vez generada la cuenta de Computer Vision API, puedes ir a la hoja


Claves y seleccionar cualquiera de las siguientes claves:

2. Accede a la aplicación Azure Functions, ajusta la Configuración de la


aplicación con el nombre Vision_API_Subscription_Key y usa cualquiera
de las claves anteriores como valor. El runtime de Azure Functions usará
esta clave para conectarse a la API de Cognitive Services y Computer Vision,
y consumirla.
3. Anota la ubicación en la que vas a crear el servicio Computer Vision. En
mi caso, he elegido Europa occidental. Al transferir imágenes a la API de
Cognitive Services, es importante asegurarse de que el punto de conexión
de la API comienza con el nombre de la ubicación. Sería algo parecido a lo
siguiente: https://westeurope.api.cognitive.microsoft.com/vision/
v1.0/analyze?visualFeatures=Faces&language=en.

Cómo hacerlo...
Sigue estos pasos:

1. Crea una función nueva mediante una de las plantillas predeterminadas con
el nombre Desencadenador de Azure Blob Storage.

[ 53 ]
Integración perfecta de Azure Functions con los Servicios de Azure

2. A continuación, debes introducir el nombre de la función de Azure junto


con la ruta y la conexión de la cuenta de almacenamiento. Se cargará
una imagen en el contenedor del desencadenador de Azure Blob Storage
(imagen) (mencionado en el parámetro Ruta de la siguiente captura
de pantalla) al final de esta sección:

Ten en cuenta que al crear la función, la plantilla crea un enlace de salida


de tabla de almacenamiento de blobs y esto nos permite proporcionar el
parámetro Nombre de tabla. Sin embargo, no se puede asignar el nombre
del parámetro al crear la función. Se puede cambiar una vez la hayamos
creado. Revisa todos los detalles y, a continuación, haz clic en el botón
Crear para crear la Azure Function.
3. Una vez creada la función, ve a la pestaña Integrar, haz clic en Nueva salida
y selecciona Almacenamiento de tablas de Azure y, a continuación, haz
clic en el botón Seleccionar. Proporciona los valores de los parámetros y,
a continuación, haz clic en el botón Guardar, como se muestra en la siguiente
captura de pantalla:

[ 54 ]
Capítulo 3

4. Ahora vamos a crear otro enlace de salida de Almacenamiento de tablas


de Azure para almacenar toda la información relativa a mujeres. Para
ello, haz clic en el botón Nueva salida de la pestaña Integrar, selecciona
Almacenamiento de tablas de Azure y haz clic en el botón Seleccionar.
Esto es lo que aparece una vez proporcionados los valores de entrada:

5. Después de revisar todos los detalles, haz clic en el botón Guardar para crear
el enlace de salida de Almacenamiento de tablas de Azure y guardar los
datos relativos a mujeres.

[ 55 ]
Integración perfecta de Azure Functions con los Servicios de Azure

6. Navega hasta el editor de código del método Run de la función


LocateMaleFemaleFaces y, a continuación, agrega los parámetros
outMaleTable y outFemaleTable. El código siguiente toma la secuencia
de imágenes cargada en el blob y esta se pasa luego como entrada
a Cognitive Services, que devuelve un JSON con toda la información de la
cara. Una vez recibida la información de la cara, incluidas las coordenadas
y los detalles de género, debemos guardar las coordenadas de la cara en el
almacenamiento de tablas correspondiente utilizando los enlaces de salida
de tablas:
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Storage"

using Newtonsoft.Json;
using Microsoft.WindowsAzure.Storage.Table;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
public static async Task Run(Stream myBlob,
string name,
IAsyncCollector<FaceRectangle>
outMaleTable,
IAsyncCollector<FaceRectangle>
outFemaleTable,
ILogger log)
{
log.LogInformation($"C# Blob trigger function Processed blob\n
Name:{name} \n Size: {myBlob.Length} Bytes");
string result = await CallVisionAPI(myBlob);
log.LogInformation(result);
if (String.IsNullOrEmpty(result))
{
return;
}
ImageData imageData = JsonConvert.DeserializeObject<ImageData>
(result);
foreach (Face face in imageData.Faces)
{
var faceRectangle = face.FaceRectangle;
faceRectangle.RowKey = Guid.NewGuid().ToString();
faceRectangle.PartitionKey = "Functions";
faceRectangle.ImageFile = name + ".jpg";
if(face.Gender=="Female")
{
await outFemaleTable.AddAsync(faceRectangle);
[ 56 ]
Capítulo 3

}
Else
{
await outMaleTable.AddAsync(faceRectangle);
}
}
}
static async Task<string> CallVisionAPI(Stream image)
{
using (var client = new HttpClient())
{
var content = new StreamContent(image);
var url = "https://westeurope.api.cognitive.microsoft.com/
vision/v1.0/analyze?visualFeatures=Faces&language=en";
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-
Key", Environment.GetEnvironmentVariable("Vision_API_Subscription_
Key"));
content.Headers.ContentType = new MediaTypeHeaderValue("ap
plication/octet-stream");
var httpResponse = await client.PostAsync(url, content);

if (httpResponse.StatusCode == HttpStatusCode.OK)
{
return await httpResponse.Content.ReadAsStringAsync();
}
}
return null;
}
public class ImageData
{
public List<Face> Faces { get; set; }
}
public class Face
{
public int Age { get; set; }
public string Gender { get; set; }
public FaceRectangle FaceRectangle { get; set; }
}
public class FaceRectangle : TableEntity
{
public string ImageFile { get; set; }
public int Left { get; set; }
public int Top { get; set; }
public int Width { get; set; }
public int Height { get; set; }}

[ 57 ]
Integración perfecta de Azure Functions con los Servicios de Azure

7. Vamos a agregar una condición (resaltada en negrita en el código


mencionado en el paso 10) para comprobar el género y, en función
de este, almacenaremos la información en el almacenamiento de tablas
correspondiente.
8. Crea un nuevo contenedor de blobs denominado imágenes mediante
el explorador de Azure Storage, como se muestra en la siguiente captura
de pantalla:

9. Vamos a cargar una imagen con rostros masculinos y femeninos en el


contenedor denominado imágenes mediante el explorador de Azure Storage,
como se muestra aquí:

[ 58 ]
Capítulo 3

10. La función se desencadena en cuanto se carga una imagen. Este es el JSON


que se registró en la consola de registros de la función:
{
"requestId":"483566bc-7d4d-45c1-87e2-6f894aaa4c29",
"metadata":{ },
"faces":[
{
"age":31,
"gender":"Female",
"faceRectangle":{
"left":535,
"top":182,
"width":165,
"height":165
}
},
{
"age":33,
"gender":"Male",
"faceRectangle":{
"left":373,
"top":182,
"width":161,
"height":161
}
}
]
}

Si eres un desarrollador de front-end con experiencia en HTML5 y


tecnologías relacionadas con lienzos, puedes incluso dibujar cuadrados
que localicen las caras en la imagen usando la información proporcionada
por Cognitive Services.

[ 59 ]
Integración perfecta de Azure Functions con los Servicios de Azure

11. La función también ha creado dos tablas de Almacenamiento de tablas


de Azure diferentes, como se muestra aquí:

Cómo funciona...
Primero hemos creado un enlace de salida de Almacenamiento de tablas para
almacenar detalles sobre todos los hombres de las fotos. Luego, hemos creado otro
enlace de salida de Almacenamiento de tablas para almacenar los detalles sobre
todas las mujeres.

Aunque usamos todo el código predeterminado que proporciona la plantilla de


Azure Functions para almacenar todas las coordenadas de caras en una sola tabla,
hemos realizado un pequeño cambio para comprobar si la persona de la foto es
hombre o mujer y almacenar los datos en función del resultado.

Ten en cuenta que las API no son 100 % exactas en la identificación del
género correcto. Por lo tanto, en tus entornos de producción, debes contar
con un mecanismo de reserva que te permita manejar estas situaciones.

Y eso no es todo…
El código predeterminado que proporciona la plantilla invoca la Computer Vision
API al pasar la imagen que hemos cargado en el almacenamiento de blobs. Las
plantillas de localización de caras invocan la llamada a API pasando el parámetro
visualFeatures=Faces, que devuelve información sobre lo siguiente:

• Edad
• Género
• Coordenadas de las caras de la imagen

[ 60 ]
Capítulo 3

Puedes obtener más información sobre Computer Vision API en


https://docs.microsoft.com/azure/cognitive-services/
computer-vision/home.

Usa la función Environment.GetEnvironmentVariable("KeyName") para


recuperar la información almacenada en la configuración de la aplicación. En este
caso, el método CallVisionAPI utiliza la función para recuperar la clave, que es
esencial para realizar una solicitud a Microsoft Cognitive Services.

Es una práctica recomendada para almacenar todas las claves y otra


información confidencial en la configuración de la aplicación.

ICollector e IAsyncCollector se usan para la inserción masiva


de datos.

Interacciones de Azure SQL Database


mediante Azure Functions
Hasta ahora, has aprendido a almacenar datos en servicios de Azure Storage, como
blobs, colas y tablas. Todos estos servicios de almacenamiento son excelentes para
almacenar datos no estructurados o semiestructurados. Sin embargo, es posible
que necesitemos almacenar datos en sistemas de administración de bases de datos
relacionales, como una Azure SQL Database.

En esta receta, aprenderás a utilizar la API de ADO.NET para conectarte a una SQL
Database e insertar datos JSON en una tabla denominada EmployeeInfo.

Preparación
Ve al portal de Azure y haz lo siguiente:

1. Crea un SQL Server lógico con el nombre que prefieras. Se recomienda


crearlo en el mismo grupo de recursos en el que se encuentren tus Azure
Functions.
2. Crea una Azure SQL Database denominada Cookbookdatabase. Para ello,
selecciona Base de datos en blanco en la lista desplegable Seleccionar origen
de la hoja SQL Database al crear la base de datos.

[ 61 ]
Integración perfecta de Azure Functions con los Servicios de Azure

3. Para crear una regla de firewall para tu dirección IP, haz clic en el botón
Establecer regla de firewall en la hoja Información general para que puedas
conectarte a las Azure SQL Databases a través de SQL Server Management
Studio (SSMS). Si no tienes SSMS, instala la versión más reciente de SSMS.
La puedes descargar en https://docs.microsoft.com/sql/ssms/
download-sql-server-management-studio-ssms.
4. Haz clic en el enlace Mostrar las cadenas de conexión de la base de datos
en la hoja Información esencial de SQL Database, como se muestra en la
siguiente captura de pantalla:

5. Copia la cadena de conexión de la hoja siguiente. No olvides reemplazar


las plantillas su_nombre_de_usuario y su_contraseña con tu nombre
de usuario y contraseña reales:

[ 62 ]
Capítulo 3

6. Abre SSMS y conéctate al servidor SQL Server lógico de Azure que creaste
en los pasos anteriores.
7. Una vez que conectado, crea una nueva tabla con el nombre EmployeeInfo
utilizando el siguiente esquema:
CREATE TABLE [dbo].[EmployeeInfo](
[PKEmployeeId] [bigint] IDENTITY(1,1) NOT NULL,
[firstname] [varchar](50) NOT NULL,
[lastname] [varchar](50) NULL,
[email] [varchar](50) NOT NULL,
[devicelist] [varchar](max) NULL,
CONSTRAINT [PK_EmployeeInfo] PRIMARY KEY CLUSTERED
(
[PKEmployeeId] ASC
)
)

Cómo hacerlo...
Sigue estos pasos:

1. Navega a la aplicación de la función, crea un nuevo desencadenador


de HTTP mediante la plantilla HttpTrigger-CSharp, establece el Nivel
de autorización en Anónimo.
2. Navega hasta el editor de código de run.csx en la función
SaveJSONToAzureSQLDatabase y reemplaza el código predeterminado
por el siguiente. El código siguiente toma los datos que se pasan al
desencadenador de HTTP y los inserta en la base de datos mediante la API
ADO.Net:
#r "Newtonsoft.Json"
#r "System.Data"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Data.SqlClient;
using System.Data;

public static async Task<IActionResult> Run(HttpRequest req,


ILogger log)
{

[ 63 ]
Integración perfecta de Azure Functions con los Servicios de Azure

log.LogInformation("C# HTTP trigger function processed a


request.");

string firstname,lastname, email, devicelist;

string requestBody = await new StreamReader(req.Body).


ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
firstname = data.firstname;
lastname = data.lastname;
email = data.email;
devicelist = data.devicelist;

SqlConnection con =null;


Try
{
string query = "INSERT INTO EmployeeInfo
(firstname,lastname, email, devicelist) " + "VALUES (@firstname,@
lastname, @email, @devicelist) ";

con = new
SqlConnection("Server=tcp:azurecookbooks.database.
windows.net,1433;Initial Catalog=Cookbookdatabase;Persist Security
Info=False;User ID=username;Password=password;MultipleActiveResu
ltSets=False;Encrypt=True;TrustServerCertificate=False;Connection
Timeout=30;");
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.Add("@firstname", SqlDbType.VarChar,
50).Value = firstname;
cmd.Parameters.Add("@lastname", SqlDbType.VarChar,
50)
.Value = lastname;
cmd.Parameters.Add("@email", SqlDbType.VarChar, 50)
.Value = email;
cmd.Parameters.Add("@devicelist", SqlDbType.VarChar)
.Value = devicelist;
con.Open();
cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
log.LogInformation(ex.Message);
}
Finally
{

[ 64 ]
Capítulo 3

if(con!=null)
{
con.Close();
}
}

return (ActionResult)new OkObjectResult($"Successfully


inserted the data.");

Ten en cuenta que debes validar todos y cada uno de los parámetros de entrada. Para
que resulte más sencillo, el código que valida los parámetros de entrada no está incluido.
Asegúrate de validar todos los parámetros antes de guardarlos en la base de datos. También
se recomienda almacenar la cadena de conexión en la Configuración de la aplicación.

3. Vamos a ejecutar el desencadenador de HTTP con los siguientes datos


de prueba directamente desde la consola de prueba de Azure Functions:
{
"firstname": "Praveen",
"lastname": "Kumar",
"email": "praveen@example.com",
"devicelist":
"[
{
'Type' : 'Mobile Phone',
'Company':'Microsoft'
},
{
'Type' : 'Laptop',
'Company':'Lenovo'
}
]"
}

Ten en cuenta que debes validar todos y cada uno de los parámetros de entrada. Para
que resulte más sencillo, el código que valida los parámetros de entrada no está incluido.
Asegúrate de validar todos los parámetros antes de guardarlos en la base de datos.

[ 65 ]
Integración perfecta de Azure Functions con los Servicios de Azure

4. Tal como se muestra en la siguiente captura de pantalla, se ha insertado


correctamente un registro:

Cómo funciona...
El objetivo de esta receta era aceptar los valores de entrada del usuario y guardarlos
en una base de datos relacional donde poder recuperar los datos posteriormente para
fines operativos. Para ello, hemos utilizado Azure SQL Database, una oferta de base
de datos relacional también conocida como base de datos como servicio (DBaaS).
Hemos creado una nueva SQL Database y reglas de firewall que nos permiten
conectar de forma remota desde la estación de trabajo de desarrollo local mediante
SSMS. También hemos creado una tabla denominada EmployeeInfo, que se puede
utilizar para guardar datos.

Hemos desarrollado un sencillo programa que utiliza la API ADO.NET, que conecta
con Azure SQL Database e inserta datos en la tabla EmployeeInfo.

Supervisar tweets a través de Logic Apps


y notificar a los usuarios publicaciones
de tweets de usuarios populares
Uno de mis colegas, que trabaja en un proyecto de gestión de reclamaciones
sociales, es responsable de supervisar los problemas que los usuarios publican en
las plataformas de redes sociales, como Facebook, Twitter y otras. Se enfrentaba al
problema de tener que supervisar continuamente los tweets publicados en la cuenta
de Twitter de su cliente con hashtags específicos. Su trabajo principal consistía en
responder rápidamente a los tweets de cuentas de usuarios con un gran número
de seguidores, es decir, a usuarios con más de 50.000 seguidores. Así pues, estaba
buscando una solución que supervisase de manera continua un hashtag concreto y
le avisase cada vez que un usuario con más de 50.000 seguidores publicase un tweet
para que su equipo respondiera rápidamente a ese usuario.
[ 66 ]
Capítulo 3

En este caso, para que resulte más sencillo, estableceremos la cifra


de 200 seguidores, en lugar de 50.000.

Antes de conocer Azure Logic Apps, pensé que llevaría varias semanas estudiar,
desarrollar, probar e implementar una solución de este tipo. Obviamente, se
necesitaría bastante tiempo para estudiar, comprender y consumir la API de Twitter
(o de cualquier otro canal social) para obtener la información necesaria y crear una
solución completa que resuelva el problema.

Afortunadamente, tras conocer Logic Apps y sus conectores listos para usar,
comprobé que apenas se tarda 10 minutos en diseñar una solución para el problema
que tenía mi amigo.

En esta receta, aprenderás a diseñar una Logic App que se integre con Twitter
(para supervisar tweets) y Gmail (para enviar correos electrónicos).

Preparación
Necesitamos lo siguiente para trabajar con esta receta:

• Una cuenta válida de Twitter


• Una cuenta válida de Gmail

Al trabajar con esta receta, tendremos que autorizar a Azure Logic Apps para
acceder a tus cuentas.

Cómo hacerlo...
Vamos a llevar a cabo los siguientes pasos:

1. Crear una Logic App nueva


2. Diseñar la Logic App con conectores de Twitter y Gmail
3. Probar la Logic App publicando los tweets con el hashtag específico

Crear una Logic App nueva


Sigue estos pasos:

1. Inicia sesión en el portal de administración de Azure, busca Logic Apps


y selecciona Logic App.

[ 67 ]
Integración perfecta de Azure Functions con los Servicios de Azure

2. En la hoja Crear aplicación lógica, una vez introducido el nombre, el grupo


de recursos, la suscripción y la ubicación, haz clic en el botón Crear para
crear la Logic App:

[ 68 ]
Capítulo 3

Diseñar la Logic App con conectores de Twitter


y Gmail
Sigue estos pasos:

1. Una vez creada la Logic App, ve al Diseñador de Logic Apps y selecciona


Aplicación lógica en blanco.
2. A continuación, habrá que introducir los Conectores. En la lista Conectores,
haz clic en Twitter. A continuación, se te pedirá que te conectes a Twitter
utilizando las credenciales de tu cuenta de Twitter. Si ya estás conectado,
se mostrará directamente la lista de Desencadenadores asociados con el
conector de Twitter, como se muestra en la siguiente captura de pantalla:

3. Después de hacer clic en el desencadenador de Twitter, se te pedirá que


proporciones el Texto de búsqueda (por ejemplo, hashtags y palabras clave)
y la Frecuencia con la que deseas que la Logic App sondee los tweets. Esto es
lo que se muestra una vez proporcionados los datos:

[ 69 ]
Integración perfecta de Azure Functions con los Servicios de Azure

4. Ahora vamos a agregar una condición nueva. Para ello, hay que hacer
clic en Siguiente paso, buscar la condición y seleccionar la acción para
la condición, como se muestra en la siguiente captura de pantalla:

5. Una vez realizado el paso anterior, se mostrará la siguiente pantalla, donde


se pueden seleccionar los valores de la condición y seleccionar lo que
desearías agregar cuando la condición se establezca como true o false:

[ 70 ]
Capítulo 3

6. Al hacer clic en el campo de entrada Elegir un valor, se mostrarán todos los


parámetros a los que se podría agregar una condición; en este caso, debemos
seleccionar Recuento de seguidores, como se muestra en la siguiente captura
de pantalla:

7. Una vez seleccionado el parámetro Recuento de seguidores, debes crear una


condición (Recuento de seguidores mayor o igual que 200), como se muestra
en la siguiente captura de pantalla:

[ 71 ]
Integración perfecta de Azure Functions con los Servicios de Azure

8. En la sección If true de la Condición anterior, busca la conexión de Gmail


y selecciona Gmail | Enviar correo electrónico, como se muestra en la
siguiente captura de pantalla:

9. Se te pedirá que inicies sesión si aún no lo has hecho. Proporciona tus


credenciales y autoriza a Azure Logic Apps para acceder a tu cuenta
de Gmail.

[ 72 ]
Capítulo 3

10. Una vez concedida la autorización, puedes enmarcar tu correo electrónico


con Agregar contenido dinámico con los parámetros de Twitter, como
se muestra en la siguiente captura de pantalla. Si no ves el Recuento
de seguidores, haz clic en el enlace Mostrar más:

Si la opción Recuento de seguidores no aparece en la pantalla, haz


clic en el enlace Mostrar más.

11. Una vez que hayas terminado, haz clic en el botón Guardar.

Probar la funcionalidad de Logic App


Sigue estos pasos:

1. Vamos a publicar un tweet en Twitter con el hashtag #AzureFunctions,


como se muestra en la siguiente captura de pantalla:

[ 73 ]
Integración perfecta de Azure Functions con los Servicios de Azure

2. Transcurrido aproximadamente un minuto, debería activarse la Logic App.


Ahora, debemos ir a la hoja de información general de la Logic App y ver el
Historial de ejecuciones:

3. Todo correcto, se ha activado dos veces y he recibido los correos electrónicos.


Uno de ellos se muestra en la siguiente captura de pantalla:

Cómo funciona...
Has creado una nueva Logic App y has elegido el conector de Twitter para
supervisar los tweets publicados con el hashtag #AzureFunctions una vez por
minuto. Si hay algún tweet con ese hashtag, la aplicación comprueba si el recuento
de seguidores es mayor o igual que 200. Si el recuento de seguidores cumple la
condición, se crea una acción nueva con un nuevo conector de Gmail que envía
un correo electrónico con el contenido dinámico que deseas enmarcar usando los
parámetros del conector de Twitter.

Integrar Logic Apps con funciones sin


servidor
En la receta anterior, has aprendido a integrar diferentes conectores mediante Logic
Apps. En esta receta, vamos a implementar la misma solución que implementamos
en la receta anterior. Para ello, moveremos simplemente la lógica condicional que
comprueba el recuento de seguidores en Azure Functions.

[ 74 ]
Capítulo 3

Preparación
Antes de seguir avanzando, vamos a realizar los siguientes pasos:

1. Crea una cuenta de SendGrid (si no se ha creado ya), obtén la clave de API
de SendGrid y crea una clave nueva en la Configuración de la aplicación
de la Function App.
2. Instala Postman para probar el desencadenador de HTTP. Puedes descargar
la herramienta en https://www.getpostman.com/.

Cómo hacerlo...
Sigue estos pasos:

1. Crea una función nueva. Para ello, selecciona el desencadenador de HTTP


y asígnale el nombre ValidateTwitterFollowerCount.
2. Ve a la pestaña Integrar y agrega un nuevo enlace de salida, SendGrid
a través del botón Nueva salida:

3. Reemplaza el código predeterminado con lo siguiente y haz clic en Guardar.


El siguiente código simplemente comprueba el recuento de seguidores y si es
mayor que 200, envía un correo electrónico:
#r "Newtonsoft.Json"
#r "SendGrid"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
[ 75 ]
Integración perfecta de Azure Functions con los Servicios de Azure

using SendGrid.Helpers.Mail;
public static async Task<IActionResult> Run(HttpRequest req, IAsyn
cCollector<SendGridMessage> messages, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a
request.");

string name = req.Query["name"];

string requestBody = await new StreamReader(req.Body).


ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);

string strTweet = "";


SendGridMessage message = new SendGridMessage();
if(data.followersCount >= 200)
{
strTweet = "Tweet Content" + data.tweettext;

message.SetSubject($"{data.Name} with {data.


followersCount} followers has posted a tweet");
message.SetFrom("donotreply@example.com");
message.AddTo("prawin2k@gmail.com");
message.AddContent("text/html", strTweet);

}
Else
{
message = null;
}
await messages.AddAsync(message);
return (ActionResult)new OkObjectResult($"Hello");
}

4. Prueba la función a través de Postman utilizando los parámetros resaltados


en la siguiente captura de pantalla. En los pasos siguientes, después de
integrar la función de Azure ValidateTwitterFollowerCount, todos los
parámetros de entrada siguientes, como followersCount, tweettext y
Name, se publicarán a través del conector de Twitter de la Logic App:

[ 76 ]
Capítulo 3

5. Crea una nueva Logic App, denominada


NotifywhenTweetedbyPopularUserUsingFunctions.
6. Comienza diseñando la aplicación con la plantilla de Aplicación lógica en
blanco, selecciona el conector de Twitter y configura Texto de búsqueda,
Frecuencia e Intervalo.
7. Haz clic en Nuevo paso para agregar una acción. En la sección Elegir una
acción, selecciona Azure Functions como conector, como se muestra en la
siguiente captura de pantalla:

[ 77 ]
Integración perfecta de Azure Functions con los Servicios de Azure

8. Al hacer clic en Azure Functions se enumerarán todas las aplicaciones


de funciones de Azure disponibles, como se muestra en la siguiente captura
de pantalla:

9. Haz clic en la Function App en la que has creado la función


ValidateTwitterFollowerCount. A continuación, selecciona la función
ValidateTwitterFollowerCount, como se muestra en la siguiente
captura de pantalla:

[ 78 ]
Capítulo 3

10. En el siguiente paso, hay que preparar la entrada JSON que se debe
pasar desde la Logic App a la función de desencadenador de HTTP
ValidateTwitterFollowerCount que hemos desarrollado. Ahora vamos
a enmarcar la entrada JSON de la misma manera que lo hicimos al probar la
función de desencadenador de HTTP mediante Postman, como se muestra
en la siguiente captura de pantalla (la única diferencia es que los valores,
como followersCount, Name y tweettext, son dinámicos ahora):

11. Una vez que hayas revisado todos los parámetros que espera la función
ValidateTwitterFollowerCount, haz clic en el botón Guardar para guardar
los cambios.
12. Puedes esperar unos minutos o publicar un tweet con el hashtag que has
configurado en el campo de entrada Texto de búsqueda.

Y eso no es todo…
Si no ves el parámetro dinámico previsto, haz clic en el botón Ver más, como
se muestra en la siguiente captura de pantalla:

[ 79 ]
Integración perfecta de Azure Functions con los Servicios de Azure

En la función de Azure ValidateTwitterFollowerCount, hemos


codificado de forma rígida el umbral de recuento de seguidores
como 200. Es recomendable guardar estos valores como elementos
configurables almacenándolos en la Configuración de la aplicación.

Consulta también
• Consulta la receta Enviar una notificación por correo electrónico al usuario final de
forma dinámica en el capítulo 2, Trabajar con notificaciones mediante los servicios
SendGrid y Twilio

Auditorías de datos de Cosmos DB


mediante desencadenadores de fuente
de cambios
Es posible que muchos de vosotros ya hayáis oído hablar de Cosmos DB, ya
que se ha vuelto muy popular y muchas organizaciones la utilizan debido a las
características que proporciona.
En esta receta, aprenderemos acerca de la integración de Azure Functions sin
servidor con una base de datos NoSQL sin servidor en Cosmos DB. Puedes obtener
más información sobre Cosmos DB en https://docs.microsoft.com/azure/
cosmos-db/introduction.
Es probable que sea necesario mantener registros de cambios de campos, atributos,
documentos y otros para fines de auditoría con cierta frecuencia. En el mundo de las
bases de datos relacionales, es posible que hayas visto desarrolladores que utilizan
desencadenadores o procedimientos almacenados para implementar este tipo de
funcionalidad de auditoría, donde se escribe código para almacenar datos en una
tabla de auditoría independiente.
En esta receta, vamos a aprender lo fácil que es llevar a la práctica el caso de uso
anterior y auditar las colecciones de Cosmos DB, para lo que simplemente tendremos
que escribir una función simple que se desencadene siempre que se realice un
cambio en un documento de una colección de Cosmos DB.

En el mundo de las bases de datos relacionales, una colección es lo mismo


que una tabla y un documento es lo mismo que un registro.

Preparación
Para poder comenzar, debemos hacer primero lo siguiente:
• Crear una cuenta de Cosmos DB
• Crear una nueva colección de Cosmos DB en la que puedas almacenar datos
en forma de documentos
[ 80 ]
Capítulo 3

Crear una nueva cuenta de Cosmos DB


Ve al portal de Azure y crea una cuenta de Cosmos DB nueva. Tendrás que
proporcionar lo siguiente:

• Una suscripción válida y un grupo de recursos.


• Un nombre de cuenta válido. Esto creará un punto de conexión en
<<nombreCuenta>>.document.azure.com.
• Una API. Establécela en SQL. De este modo, podrás escribir consultas
en SQL. Puedes utilizar cualquier otra API si lo deseas.

Crear una nueva colección de Cosmos DB


Sigue estos pasos:

1. Una vez creada la cuenta, tendrás que crear una base de datos nueva
y una colección. Podemos crear las dos en un solo paso directamente desde
el portal.
2. Ve a la pestaña Información general y haz clic en el botón Agregar colección
para crear una colección nueva:

3. A continuación, se abrirá automáticamente la pestaña Explorador de datos,


donde se te pedirá que proporciones los siguientes datos:
Nombre de campo Valor Comentario
Id. de base de Se trata de un contenedor de
cookbookdatabase
datos varias colecciones de Cosmos DB.
Este es el nombre de la colección
Id. de colección cookbookdatacollection
donde vas a almacenar los datos.

[ 81 ]
Integración perfecta de Azure Functions con los Servicios de Azure

Nombre de campo Valor Comentario


En función de las cargas de
trabajo de producción, es posible
Capacidad de
Fijo (10 GB) que necesites una capacidad
almacenamiento
ilimitada, ya que, de lo contrario,
se realizarán particiones.
Esta es la capacidad de la
colección de Cosmos DB. El
rendimiento de las lecturas
Rendimiento
400 y escrituras de la colección
(400-10.000 RU/s)
depende del rendimiento que
configures al aprovisionar la
colección.

4. A continuación, haz clic en el botón Aceptar para crear la colección. Si todo


ha ido bien, se mostrará algo parecido a lo siguiente en la pestaña Explorador
de datos de la cuenta de Cosmos DB:

Hemos creado correctamente una cuenta de Cosmos DB y una colección. Ahora


vamos a aprender a integrar la colección con una nueva función de Azure y cómo
hacer que se active cada vez que se realice un cambio en la colección de Cosmos DB.

Cómo hacerlo...
Sigue estos pasos:

1. Ve a la cuenta de Cosmos DB y haz clic en el menú Agregar Azure Function


de la hoja Todas las configuraciones en la cuenta de Cosmos DB.

[ 82 ]
Capítulo 3

2. Ahora se abrirá la hoja Agregar Azure Function, donde deberás elegir la


aplicación de la función de Azure en la que te gustaría crear una nueva
función (desencadenador de Cosmos DB) para que se active cada vez
que se realice un cambio en la colección. Esto es lo que se muestra:

[ 83 ]
Integración perfecta de Azure Functions con los Servicios de Azure

3. Una vez que hayas revisado los detalles, haz clic en el botón Guardar (que
se muestra en la captura de pantalla anterior) para crear la nueva función,
que se activará cada vez que se realice un cambio en la colección. Ahora,
iremos rápidamente a la aplicación de la función de Azure (en mi caso, es
AzureFunctionCookBookV2) para ver si se ha creado la función nueva con
el nombre cookbookdatacollectionTrigger. Esto es lo que aparece en la
aplicación de mi función:

4. Reemplaza el código predeterminado con el siguiente código del


desencadenador de Azure Functions Cosmos DB y así obtendrás una lista
de todos los documentos que se han actualizado. El código siguiente solo
imprime el número de documentos que se han actualizado y el Id. del
primer documento en la consola de registros:
#r "Microsoft.Azure.DocumentDB.Core"
using System;
using System.Collections.Generic;
using Microsoft.Azure.Documents;

public static void Run(IReadOnlyList<Document> input, ILogger log)


{
[ 84 ]
Capítulo 3

if (input != null && input.Count > 0)


{
log.LogInformation("Documents modified " + input.Count);
log.LogInformation("First document Id " + input[0].Id);
}
}

5. Así se habrá completado la integración de la colección de Cosmos DB y


la función de Azure. Ahora vamos a agregar un documento nuevo a la
colección y ver cómo se activa el desencadenador. Abre una pestaña nueva
(deja la pestaña cookbookdatacollectionTrigger abierta en el explorador),
ve a la colección y crea un documento nuevo. Para ello, haz clic en el botón
Nuevo documento, como se muestra en la siguiente captura de pantalla:

6. Una vez que hayas reemplazado el JSON predeterminado (que solo tiene
un atributo Id.) con el JSON que tiene los atributos necesarios, haz clic en
el botón Guardar para guardar los cambios y acceder rápidamente a la
pestaña del otro navegador, donde está abierta la función de Azure,
y revisar los registros para comprobar la salida de la función. Así es como
se muestran mis registros justo después de agregar un valor al atributo Id.
del documento. Puede que a ti te aparezca de otra forma, va a depender
de la estructura JSON:

[ 85 ]
Integración perfecta de Azure Functions con los Servicios de Azure

Cómo funciona...
Para integrar las Azure Functions con Cosmos DB, primero hemos creado una
cuenta de Cosmos DB, a continuación, una base de datos y, dentro de esta, una
colección nueva. Una vez creada la colección, la hemos integrado desde el portal
de Azure. Para ello, hemos hecho clic en el botón Agregar Azure Function, que está
disponible en el nivel de cuenta de Cosmos DB. Hemos elegido la Function App
necesaria en la que queríamos crear un desencadenador de Cosmos DB. Una vez
finalizada la integración, hemos creado un documento de muestra en la colección
de Cosmos DB y, a continuación, hemos comprobado que la función se ha activado
automáticamente para todos los cambios (todas las lecturas y escrituras, pero no las
eliminaciones) que hemos realizado en la colección.

Y eso no es todo…
Al integrar Azure Functions para realizar un seguimiento de los cambios de Cosmos
DB, se creará automáticamente una colección nueva denominada concesiones, como
se muestra aquí. Ten en cuenta que esto conlleva coste adicional, ya que el coste en
Cosmos DB se basa en las unidades de solicitud (RU) asignadas a cada colección:

Es importante tener en cuenta que el desencadenador de Cosmos DB no se activaría


(en el momento en que se redactó la receta) para ninguna de las eliminaciones de
la colección. Solo se activa para crear y actualizar los documentos de una colección.
Si para ti es importante llevar un seguimiento de las eliminaciones, tendrás que
realizar eliminaciones temporales, es decir, tendrás que establecer un atributo como
isDeleted en true para los registros que elimine la aplicación y que estén basados
en el atributo isDeleted, implementando así una lógica personalizada
en el desencadenador de Cosmos DB.
La integración que hemos realizado entre Azure Functions y Cosmos DB utiliza las
fuentes de cambios de Cosmos DB. Puedes obtener más información sobre fuentes
de cambios aquí: https://docs.microsoft.com/azure/cosmos-db/change-feed.
No olvides eliminar la cuenta de Cosmos DB y las colecciones asociadas si crees que
no vas a volver a utilizarlas, ya que las colecciones se cobran en función de las RU
asignadas aunque no las estés utilizando de manera activa.
Si no puedes ejecutar esta función de Azure o te aparece un mensaje de error
indicando que las extensiones de Cosmos DB no están instaladas, intenta crear un
nuevo desencadenador de Cosmos DB, que solicitará la instalación.

[ 86 ]
Comprender la experiencia
de desarrollador integrada de
Visual Studio Tools
En este capítulo, explicaremos lo siguiente:
• Crear una aplicación de función con Visual Studio 2017
• Depurar Azure Functions de C# en un entorno preconfigurado local usando
Visual Studio 2017
• Cómo conectarse al cloud de Azure Storage desde el entorno local de
Visual Studio
• Implementar la aplicación Azure Function en Azure Cloud mediante
Visual Studio
• Depurar en vivo Azure Function de C#, que se hospeda en el entorno
en el cloud de Microsoft Azure, utilizando Visual Studio
• Implementar Azure Functions en un contenedor

Introducción
En todos los capítulos anteriores, hemos visto cómo crear Azure Functions
directamente desde el portal de administración de Azure. A continuación,
vemos algunas de las características:

• Puedes crear rápidamente una función seleccionando simplemente una de las


plantillas integradas que se proporcionan en el runtime de Azure Function
• Los desarrolladores no deben preocuparse por escribir el código
de asociación y entender cómo funcionan los marcos
• Los cambios de configuración se pueden hacer dentro de la interfaz
de usuario utilizando el editor estándar
[ 87 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

A pesar de todas las ventajas mencionadas, puede que los desarrolladores no lo vean
cómodo si se acostumbraron a trabajar con sus entornos de desarrollo integrado
(IDE) favoritos hace mucho tiempo. Por lo tanto, el equipo de Microsoft ha creado
algunas herramientas que ayudan a los desarrolladores a integrarlos en Visual
Studio para que puedan aprovechar algunas de las características IDE importantes
que aceleran sus esfuerzos de desarrollo. Aquí tenemos algunas:

• Los desarrolladores se benefician del soporte de IntelliSense


• Puedes depurar código línea por línea
• Puedes ver rápidamente los valores de las variables mientras estás
depurando la aplicación
• Integración con sistemas de control de versiones como Azure DevOps
(anteriormente, se denominaba Visual Studio Team Services (VSTS))

Actualmente, en el momento de la escritura, las herramientas de Visual Studio de la


función admiten la depuración solo para C#. En el futuro, es probable que Microsoft
presente todas estas magníficas características para otros idiomas.

Descubrirás algunas de las características mencionadas anteriormente en este


capítulo y verás cómo integrar el código con Azure DevOps en el capítulo 11,
Implementar la integración continua mediante Azure DevOps.

Crear una aplicación de función


con Visual Studio 2017
En esta receta, verás cómo crear una Azure Function para tu IDE favorito
en Visual Studio 2017.

Preparación
Debes descargar e instalar el software y las herramientas siguientes:

1. Descarga la versión más reciente de Visual Studio 2017. Puedes hacerlo


desde https://visualstudio.microsoft.com/downloads/.
2. Durante la instalación, elige la sección Desarrollo de Azure en las cargas
de trabajo, como se muestra en la siguiente captura de pantalla y, a
continuación, haz clic en el botón Instalar:

[ 88 ]
Capítulo 4

3. Desplázate hasta Herramientas | Extensiones y actualizaciones y


comprueba si hay alguna actualización de las herramientas de Visual Studio
para Azure Functions, como se muestra en la siguiente captura de pantalla:

[ 89 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Cómo hacerlo...
Sigue estos pasos:

1. Abre Visual Studio, selecciona Archivo y, a continuación, haz clic en Nuevo


proyecto. En el cuadro de diálogo Nuevo proyecto, en Plantillas instaladas,
en Visual C#, selecciona Cloud y, a continuación, selecciona la plantilla
Azure Functions:

2. Escribe el nombre de la aplicación de función. Haz clic en el botón Aceptar


para pasar al paso siguiente. Como se muestra en la siguiente captura de
pantalla, selecciona Azure Funtions v2 (.NET Core) en el menú desplegable
y, a continuación, Desencadenador de HTTP y haz clic en el botón Aceptar:

[ 90 ]
Capítulo 4

3. Hemos creado correctamente la aplicación Azure Function junto con un


desencadenador de HTTP (que acepta solicitudes web y envía una respuesta
al cliente) con el nombre Function1. Siéntete libre de cambiar el nombre
predeterminado de la aplicación de función y también asegúrate de compilar
la aplicación para descargar los paquetes de NuGet necesarios, si los hay.
4. Después de crear una nueva función, también se creará una clase nueva,
como se muestra en la siguiente captura de pantalla:

Ahora hemos creado correctamente una nueva aplicación de función desencadenada


por HTTP con Visual Studio 2017.

[ 91 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Cómo funciona...
Las herramientas de Visual Studio de Azure Functions permiten a los
desarrolladores usar su IDE favorito, que puede que lleven años utilizando. Con
las herramientas de Azure Function, puedes usar el mismo conjunto de plantillas
que proporciona el portal de administración de Azure para la rápida creación e
integración con los servicios en el cloud sin escribir ningún código de asociación
(o un código mínimo).
La otra ventaja de usar las herramientas de Visual Studio para las funciones es que
no es necesario tener una suscripción a Azure en vivo. Puedes depurar y probar
Azure Functions directamente en tu entorno de desarrollo local. La CLI de Azure
y las utilidades relacionadas nos brindan toda la asistencia necesaria para ejecutar
Azure Functions.

Y eso no es todo…
Uno de los problemas más comunes a los que se enfrentan los desarrolladores al
desarrollar cualquier aplicación en su entorno local es que todo funciona bien en el
equipo local, pero no en el entorno de producción. Cuando hablamos de Azure Functions,
los desarrolladores no deben preocuparse acerca de esto. El runtime de Azure
Functions, proporcionado por las herramientas de la CLI de Azure, es exactamente
el mismo runtime disponible en Azure Cloud.

Ten en cuenta que siempre puedes usar y desencadenar un servicio de


Azure que se ejecute en el cloud, incluso cuando estés desarrollando
Azure Functions localmente.

Depurar Azure Functions de C# en un


entorno preconfigurado local usando
Visual Studio 2017
Una vez finalizada la configuración básica de la creación de nuestra función,
el siguiente paso es empezar a trabajar en el desarrollo de la aplicación en función
de tus necesidades. Desarrollar código a diario no es en absoluto una tarea sencilla;
los desarrolladores se encuentran con todo tipo de problemas técnicos. Necesitan
herramientas que les ayuden a identificar la causa raíz del problema y solucionarlo
para asegurarse de que están suministrando la solución. Entre estas herramientas se
incluyen herramientas de depuración que ayudan a los desarrolladores a adentrarse
en cada línea del código para ver los valores de la variable y los objetos y obtener
una vista detallada de las excepciones.
En esta receta, aprenderás a configurar y depurar una Azure Function en un entorno
de desarrollo local dentro de Visual Studio.
[ 92 ]
Capítulo 4

Preparación
Descarga e instala la CLI de Azure (si no tienes estas herramientas instaladas, ten
en cuenta que Visual Studio las descargará automáticamente cuando ejecutes tus
funciones desde Visual Studio).

Cómo hacerlo...
Sigue estos pasos:

1. En nuestra receta anterior, creamos la función HTTPTrigger con


Visual Studio. Compilemos la aplicación haciendo clic en Compilar
y, a continuación, en Compilar solución.
2. Abre el archivo HTTPTriggerCSharpFromVS.cs y crea un punto de
interrupción presionando la tecla F9, como se muestra en la siguiente captura
de pantalla:

[ 93 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

3. Presiona la tecla F5 para empezar a depurar la función. Al presionar F5 por


primera vez, Visual Studio te pide que descargues las herramientas de la
CLI de Visual Studio si aún no las tienes instaladas. Estas herramientas son
esenciales para ejecutar una Azure Function en Visual Studio:

Ahora, se ha cambiado el nombre de la CLI de Azure Function por


el de Azure Function Core Tools. Puedes obtener más información
acerca de este tema en https://www.npmjs.com/package/azure-
functions-core-tools.

4. Al hacer clic en Sí en la captura de pantalla anterior se iniciará la descarga


de las herramientas de la CLI. La descarga y la instalación de las
herramientas de la CLI tardará unos minutos.
5. Una vez instaladas correctamente las herramientas de la CLI de Azure
Function, se creará e iniciará un host de trabajo. Se inicia la supervisión
de solicitudes en un puerto específico de todas las funciones de nuestra
aplicación de función. En la siguiente captura de pantalla se muestra que
el host de trabajo ha comenzado a supervisar las solicitudes a la aplicación
de función:

[ 94 ]
Capítulo 4

6. Vamos a tratar de acceder a la aplicación de función realizando una solicitud


a http://localhost:7071 en tu navegador favorito:

[ 95 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

7. Ahora, escribe la dirección URL completa de nuestro desencadenador


de HTTP en el navegador. Debería tener el siguiente aspecto: http://
localhost:7071/api/HttpTriggerCsharpFromVS?name=Praveen
Sreeram.
8. Después de escribir la dirección URL correcta de la Azure Function, en
cuanto presionamos la tecla Entrar en la barra de direcciones del navegador,
el depurador de Visual Studio también ejecuta el punto de depuración
(si dispones de uno), como se muestra en la siguiente captura de pantalla:

9. También puedes ver los datos de tus variables, como se muestra en la


siguiente captura de pantalla:

10. Una vez completada la depuración, puedes hacer clic en la tecla F5 para
finalizar el proceso de ejecución, después del cual verás la respuesta de salida
en el navegador, como se muestra en la siguiente captura de pantalla:

11. El registro de ejecución de la función se verá en la consola del host de trabajo,


como se muestra en la siguiente captura de pantalla:
[ 96 ]
Capítulo 4

12. Puedes agregar más Azure Functions a la aplicación de función, si es


necesario. En la siguiente receta, veremos cómo conectarse al cloud de
Azure Storage desde el entorno local.

Cómo funciona...
El host de trabajo funciona como un servidor que escucha un puerto específico.
Si hay alguna solicitud a ese puerto en concreto, automáticamente se encarga de
ejecutar las solicitudes y envía una respuesta.

La consola del host de trabajo te proporciona la siguiente información:

• El estado de la ejecución, junto con los datos de solicitud y respuesta


• Los detalles sobre todas las funciones disponibles en la aplicación de función

Y eso no es todo…
Al usar Visual Studio, puedes crear directamente funciones precompiladas, lo que
significa que cuando compilas tus funciones, Visual Studio crea un archivo .dll
al que se puede hacer referencia en otras aplicaciones, tal como lo haces para las
clases normales. A continuación, se enumeran dos de las ventajas de usar funciones
precompiladas:

• Las funciones precompiladas tienen un mejor rendimiento, ya que no se


requiere que se compilen sobre la marcha
• Puedes convertir tus clases tradicionales en Azure Functions fácilmente
y consultarlas en otras aplicaciones sin problemas

[ 97 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Cómo conectarse al cloud de Azure


Storage desde el entorno local
de Visual Studio
En las dos recetas anteriores, has aprendido a crear y ejecutar Azure Functions en un
entorno local. Desencadenamos la función desde un navegador local. Sin embargo,
en esta receta, aprenderás a activar una Azure Function en tu entorno local cuando
ocurra un evento en Azure. Por ejemplo, cuando se crea un nuevo blob en una cuenta
de Azure Storage, puedes activar tu función en tu equipo local. Esto ayuda a los
desarrolladores a probar sus aplicaciones por adelantado, antes de implementarlas
en el entorno de producción.

Preparación
Establece los siguientes requisitos previos:

1. Crea una cuenta de almacenamiento y, a continuación, un contenedor


de blob denominado cookbookfiles, en Azure.
2. Instala el explorador de Microsoft Azure Storage desde
http://storageexplorer.com/.

Cómo hacerlo...
Sigue estos pasos:

1. Abre la aplicación de Azure Function FunctionAppInVisualStudio en


Visual Studio y, a continuación, agrega una función nueva haciendo clic con
el botón derecho del ratón en el proyecto FunctionAppInVisualStudio. Haz
clic en Agregar | Nueva Azure Function, que abre una ventana emergente.
Aquí, en el campo de nombre, escribe BlobTriggerCSharp y, a continuación,
haz clic en el botón Agregar.
2. Esto abre otra ventana emergente, donde puedes proporcionar otros
parámetros, como se muestra en la siguiente captura de pantalla:

[ 98 ]
Capítulo 4

3. En la configuración de conexión de la cuenta de almacenamiento,


escribe AzureWebJobsStorage como nombre de la cadena de conexión
y proporciona también el nombre del contenedor de blob (en mi caso, es
cookbookfiles) en el campo de entrada Ruta y, a continuación, haz clic en
el botón Aceptar para crear la nueva función del desencadenador de blob. Se
crea una nueva función del desencadenador de blob, como se muestra en la
siguiente captura de pantalla:

[ 99 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

4. Si recuerdas la receta Crear una API web back-end mediante


desencadenadores de HTTP del capítulo 1, Desarrollar aplicaciones en el cloud
mediante desencadenadores y enlaces de funciones, el portal de administración de
Azure nos permite seleccionar entre una cuenta de almacenamiento nueva o
una existente. Sin embargo, el cuadro de diálogo anterior no está conectado a
tu suscripción de Azure. Por lo tanto, debes ir a la cuenta de almacenamiento
y copiar la cadena de conexión, que se puede encontrar en la hoja Claves de
acceso de la cuenta de almacenamiento en el portal de administración de
Azure, como se muestra en la siguiente captura de pantalla:

5. Pega la cadena de conexión en el archivo local.settings.json, que se


encuentra en la carpeta raíz del proyecto. Este archivo se crea cuando creas
la aplicación de función. Después de agregar la cadena de conexión a la clave
denominada AzureWebJobsStorage, el archivo local.settings.json debe
tener el aspecto que se muestra en la siguiente captura de pantalla:

6. Abre el archivo BlobTriggerCSharp.cs y crea un punto de interrupción,


como se muestra en la siguiente captura de pantalla:
[ 100 ]
Capítulo 4

7. Ahora presiona la tecla F5 para iniciar el host de trabajo, como se muestra en


la siguiente captura de pantalla:

8. He agregado un archivo blob nuevo con el explorador de Azure Storage,


como se muestra en la siguiente captura de pantalla:

[ 101 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

9. En cuanto se haya agregado el blob al contenedor especificado (en este caso,


es cookbookfiles), que se encuentra en el cloud en una ubicación remota, el
host de trabajo que se ejecuta en mi equipo local detecta que se ha agregado
un nuevo blob y el depurador ejecuta la función, como se muestra en la
siguiente captura de pantalla:

Cómo funciona...
En esta clase BlobTriggerCSharp, el método Run tiene los atributos de WebJobs
con una cadena de conexión (en este caso, es AzureWebJobsStorage). Esto indica
al runtime que consulte la cadena de conexión de Azure Storage en el archivo de
configuración de opciones local con la clave nombrada después de la cadena de
conexión AzureWebJobsStorage. Cuando el host de trabajo se empieza a ejecutar,
usa la cadena de conexión y mantiene el control de los contenedores de las cuentas de
almacenamiento que hemos especificado. Cada vez que se agrega o actualiza un nuevo
blob, desencadena automáticamente el desencadenador de blob en el entorno actual.

Y eso no es todo…
Al crear Azure Functions en el portal de administración de Azure, debes crear
desencadenadores y enlaces de salida en la pestaña Integrar de cada Azure Function.
Sin embargo, cuando creas una función desde el IDE de Visual Studio 2017, solo
puedes configurar los atributos de WebJobs para lograrlo.

Puedes obtener más información sobre los atributos de WebJobs


en https://docs.microsoft.com/azure/app-service/
webjobs-sdk-get-started.

[ 102 ]
Capítulo 4

Implementar la aplicación Azure Function


en Azure Cloud mediante Visual Studio
Hasta ahora, nuestra aplicación de función es solo una aplicación normal dentro
de Visual Studio. Para implementar la aplicación de función junto con sus funciones,
o bien tenemos que crear los siguientes recursos nuevos o bien seleccionar los
recursos existentes para hospedar la nueva aplicación de función:

• El grupo de recursos
• El plan de App Service
• La aplicación Azure Function

Puedes proporcionar toda esta información directamente desde Visual Studio sin
abrir el portal de administración de Azure. Aprenderás a hacer eso en esta receta.

Cómo hacerlo...
Sigue estos pasos:

1. Haz clic con el botón derecho en el proyecto y, a continuación, haz clic


en el botón Publicar para abrir la ventana de publicación.
2. En la ventana Publicar, selecciona la opción Crear nuevo y haz clic
en el botón Publicar, como se muestra en la siguiente captura de pantalla:

[ 103 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

3. En la ventana Crear App Service, puedes seleccionar entre los recursos


existentes o hacer clic en el botón Nuevo para seleccionar el nuevo Grupo
de recursos, el plan de App Service y la cuenta de almacenamiento, como
se muestra en la siguiente captura de pantalla:

4. En la mayoría de los casos, lo mejor es utilizar el plan Consumo para el


hosting de Azure Functions, a menos que tengas una razón convincente
para no hacerlo y prefieras utilizar uno de los App Services existentes. Para
seleccionar el plan de Consumo, tienes que hacer clic en el botón Nuevo que
está disponible para el plan de App Service, como se muestra en la captura
de pantalla anterior. Selecciona Consumo en el menú desplegable Tamaño y,
a continuación, haz clic en el botón Aceptar, como se muestra en la siguiente
captura de pantalla:

[ 104 ]
Capítulo 4

5. Después de revisar toda la información, haz clic en el botón Crear


de la ventana Crear App Service. Al hacer esto, se deberían empezar
a implementar los servicios en Azure, como se muestra en la siguiente
captura de pantalla:

6. Si todo va bien, puedes ver la aplicación de función recién creada en el portal


de administración de Azure, como se muestra en la siguiente captura de
pantalla:

[ 105 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

7. ¡Cuidado! Nuestro trabajo en Visual Studio aún no ha terminado. Acabamos


de crear los servicios requeridos en Azure directamente desde el IDE
de Visual Studio. Nuestro siguiente trabajo es publicar el código de la
estación de trabajo local en el cloud de Azure. Tan pronto como finalice la
implementación, serás dirigido al paso de Web Deploy, como se muestra en
la captura de pantalla. Haz clic en el botón Publicar para iniciar el proceso
de publicación del código:

8. Después de unos segundos, deberías ver algo similar a la siguiente captura


de pantalla en la ventana Salida de tu instancia de Visual Studio:

9. Eso es todo. Hemos finalizado la implementación de tu aplicación de función


y sus funciones en Azure directamente desde tu IDE de desarrollo favorita,
Visual Studio. Puedes revisar la implementación de la función en el portal de
administración de Azure. Las dos Azure Functions se crearon correctamente,
como se muestra en la siguiente captura de pantalla:

[ 106 ]
Capítulo 4

Y eso no es todo…
Las Azure Functions creadas desde Visual Studio 2017 están precompiladas, lo
que significa que implementas los archivos .dll de Visual Studio 2017 en Azure.
Por lo tanto, no puedes editar el código de las funciones en Azure después de
implementarlas. Sin embargo, puedes realizar cambios en las opciones, como
cambiar la cadena de conexión de Azure Storage, la ruta del contenedor, etc.
Vamos a ver cómo hacerlo en la siguiente receta.

Depurar en vivo Azure Function de C#,


que se hospeda en el entorno en el cloud
de Microsoft Azure, utilizando Visual
Studio
En una de las recetas anteriores, Cómo conectarse al cloud de Azure Storage desde
el entorno local de Visual Studio, has aprendido a conectar la cuenta en el cloud
desde el código local. En esta receta, aprenderás a depurar el código activo que se
ejecuta en el entorno de Azure Cloud. Vamos a seguir estos pasos en la función
BlobTriggerCSharp de la aplicación de función FunctionAppinVisualStudio:

• Cambiar la ruta del contenedor en el portal de administración de Azure por


la del nuevo contenedor
• Abrir la aplicación de función en Visual Studio 2017
• Adjuntar el depurador desde dentro de Visual Studio 2017 a la Azure
Function necesaria
• Crear un blob en el nuevo contenedor de almacenamiento
• Depurar la aplicación después de ejecutar los puntos de interrupción

[ 107 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Preparación
Crea un contenedor denominado cookbookfiles-live en la cuenta de
almacenamiento. Vamos a cargar un blob en este contenedor.

Cómo hacerlo...
Sigue estos pasos:

1. Ve a la función BlobTriggerCSharp en el portal de administración de


Azure y cambia la ruta de la variable path para apuntar al nuevo contenedor
cookbookfiles-live. Luego, vuelve a publicarla. Debe parecerse a cómo
se muestra en la siguiente captura de pantalla:

2. Abre la aplicación de función en Visual Studio 2017. Abre


Server Explorer y desplázate a tu Azure Function; en este caso,
FunctionAppinVisualStudio2017, como se muestra en la siguiente
captura de pantalla:

[ 108 ]
Capítulo 4

3. Haz clic con el botón derecho en la función y en Adjuntar depurador,


como se muestra en la siguiente captura de pantalla:

[ 109 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

4. Visual Studio tardará un poco de tiempo en habilitar la depuración remota,


como se muestra en la siguiente captura de pantalla:

5. La dirección URL de la aplicación de función se abrirá en el navegador,


como se muestra en la siguiente captura de pantalla, lo que indica que
nuestra aplicación de función se está ejecutando:

6. Ve al explorador de Storage y carga un archivo nuevo (en este caso, he


cargado EmployeeInfo.json) en el contenedor cookbookfiles-live,
como se muestra en la siguiente captura de pantalla:

[ 110 ]
Capítulo 4

7. Después de unos momentos, se ejecutará el punto de interrupción de la


depuración, que se muestra a continuación, donde puedes ver el nombre
de archivo que se ha cargado:

Implementar Azure Functions en un


contenedor
A estas alturas, es probable que hayas comprendido el principal caso de uso de
por qué debes usar Azure Functions. Sí, al desarrollar un fragmento de código e
implementarlo en un entorno sin servidor, donde un desarrollador o administrador
no debe preocuparse por el aprovisionamiento y el escalado de las instancias para el
hosting de tus aplicaciones del lado del servidor.

Realizar todas las funciones del entorno sin servidor solo se


puede lograr al crear la aplicación de función, seleccionando el
plan Consumo en el menú desplegable Plan de hosting.
[ 111 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Al ver el título de esta receta, es posible que ya te estés preguntando por qué y cómo
puede ser útil la implementación de Azure Function en un contenedor de Docker.
Exacto, la combinación de Azure Functions y el contenedor de Docker podría no
tener sentido, ya que perderías todas las ventajas de Azure Functions sin servidor
al realizar la implementación en Docker. Sin embargo, puede haber algunos clientes
cuyas cargas de trabajo existentes puedan estar en algún cloud (ya sea público o
privado), pero ahora quieren aprovechar algunos de los desencadenadores de Azure
Function y los servicios de Azure relacionados, por lo que querrán implementar
Azure Functions como una imagen de Docker. Esta receta trata sobre cómo
implementar esto.

Preparación
A continuación, se indican los requisitos previos para empezar a trabajar con
esta receta:

• Instala la CLI de Azure desde https://docs.microsoft.com/cli/azure/


install-azure-cli?view=azure-cli-latest
• Puedes descargar Docker en https://store.docker.com/editions/
community/docker-ce-desktop-windows. Asegúrate de instalar la versión
de Docker que sea compatible con el sistema operativo de tu entorno de
desarrollo.
• También se requiere un conocimiento básico de Docker y sus comandos
para poder compilar y ejecutar imágenes de Docker. Si te falta información,
puedes revisar la documentación oficial de Docker acerca de este tema.
• Crea un Azure Container Registry (ACR) con los pasos siguientes. Esto se
puede utilizar como un repositorio para todas las imágenes de Docker.

[ 112 ]
Capítulo 4

Creación de un ACR
Sigue estos pasos:

1. Crea un nuevo ACR proporcionando los siguientes detalles, como se muestra


en la siguiente captura de pantalla:

[ 113 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

2. Una vez creado el ACR correctamente, desplázate a la hoja Claves de


acceso y anota el servidor de inicio de sesión, el nombre de usuario y la
contraseña, que aparecen resaltados en la captura de pantalla siguiente.
Estos campos los utilizarás más adelante en esta receta:

Cómo hacerlo...
En los tres primeros capítulos, hemos creado la aplicación de función y las funciones
en el portal. Y, hasta el momento, en este capítulo, hemos creado la aplicación de
función y las funciones en Visual Studio.

Antes de comenzar, hagamos un pequeño cambio en HTTPTrigger, para que


entendamos que el código se está ejecutando desde Docker, como se resalta en la
siguiente imagen. Para ello, acabo de agregar un mensaje de Docker a la salida,
de la siguiente manera:

[ 114 ]
Capítulo 4

Crear una imagen de Docker para la


aplicación de función
Sigue estos pasos:

1. El primer paso para crear una imagen de Docker es crear un Dockerfile en


nuestro proyecto de Visual Studio. Crea un .Dockerfile con el siguiente
contenido:
FROM microsoft/azure-functions-dotnet-core2.0:2.0 COPY ./bin/
Release/netstandard2.0 /home/site/wwwroot

2. A continuación, ve al símbolo del sistema y ejecuta el siguiente comando de


Docker, docker build -t functionsindocker; no te olvides de incluir el
punto al final del comando para crear una imagen de Docker. Después de
ejecutar el comando docker build, el resultado debe ser algo parecido a lo
que se muestra en la siguiente captura de pantalla:

3. Una vez que la imagen se haya creado correctamente, el siguiente paso


es ejecutar la imagen de Docker en un puerto específico. Para ello, ejecuta
el comando. Deberías ver algo similar a lo que se muestra en la siguiente
captura de pantalla:

[ 115 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

4. Comprueba que todo funciona bien en el entorno local navegando al host


local con el puerto correcto, como se muestra en la siguiente captura de
pantalla.

Insertar la imagen de Docker en el ACR


Sigue estos pasos:

1. El primer paso es asegurarse de que proporcionamos una etiqueta


válida a la imagen con el comando docker tag functionsindocker
cookbookregistry.azurecr.io/functionsindocker:v1. Ejecutar este
comando no proporcionará ningún resultado. Sin embargo, para ver nuestros
cambios, tenemos que ejecutar el comando docker images, como se muestra
en la siguiente captura de pantalla:

2. Para insertar la imagen en ACR, debes autenticarte en Azure. Para ello,


puedes usar comandos de la CLI de Azure. Debemos iniciar sesión en Azure
con el comando az login. Al ejecutar este comando, se abrirá un navegador
y se autenticarán tus credenciales, como se muestra en la siguiente captura
de pantalla:

[ 116 ]
Capítulo 4

3. El siguiente paso es autenticarte en el ACR con el comando az acr login


--name cookbookregistry. Sustituye el nombre del ACR (en mi caso es
cookbookregistry) por el de uno que hayas creado:

4. Después de autenticarte, puedes insertar la imagen en el ACR


ejecutando el comando docker push cookbookregistry.azurecr.io/
functionsindocker:v1, como se muestra en la siguiente captura
de pantalla:

5. A continuación, vamos hasta ACR en el portal de Azure y revisamos si


nuestra imagen se insertó correctamente en la hoja Repositorios, como se
muestra en la siguiente captura de pantalla:

Hemos creado correctamente una imagen y la hemos insertado en ACR. Ahora es el


momento de crear la Azure Function y consultar la imagen de Docker que se insertó
en el ACR.
[ 117 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

Crear una nueva aplicación de función


con Docker
Sigue estos pasos:

1. Desplázate hasta la hoja Nuevo | Aplicación de función y proporciona la


siguiente información:

2. Ahora, selecciona Linux (Preview) en el campo SO y elige Imagen de


Docker en el campo Publicar; a continuación, haz clic en Ubicación/Plan de
App Service, como se muestra en la captura de pantalla anterior. Aquí, elige
crear un nuevo plan de App Service básico.
[ 118 ]
Capítulo 4

3. El paso siguiente y más importante es consultar la imagen que hemos


insertado en el ACR. Esto se puede lograr haciendo clic en el botón
Configurar contenedor y seleccionando el Azure Container Registry;
a continuación, selecciona la imagen correcta, como se muestra en la
siguiente captura de pantalla:

4. Después de revisar todos los detalles, haz clic en el botón Crear para crear la
aplicación de función.
5. Eso es todo. Hemos creado una aplicación de función que nos permite
implementar las imágenes de Docker enlazándolas a la imagen hospedada
en Azure Container Registry. Vamos a probar rápidamente HttpTrigger
navegando hasta el punto de conexión de HTTP en el navegador.
A continuación, vemos el resultado de Azure Function.

Cómo funciona...
En los tres primeros capítulos, hemos creado la aplicación de función y las funciones
en el portal. Por el contrario, hasta el momento, en este capítulo, hemos creado la
aplicación de función y las funciones en Visual Studio.

[ 119 ]
Comprender la experiencia de desarrollador integrada de Visual Studio Tools

En esta receta, hemos realizado lo siguiente:

Los puntos numerados de este diagrama hacen referencia a los pasos siguientes:

1. Crear una imagen de Docker de la aplicación de función que hemos creado


en este capítulo con Visual Studio.
2. Insertar la imagen de Docker en el ACR
3. Desde el portal, crear una nueva aplicación de función, eligiendo publicar
el paquete ejecutable como una imagen de Docker.
4. Adjuntar la imagen de Docker desde el ACR (paso 2 de la guía anterior)
a Azure Function (paso 3 de la guía anterior)

[ 120 ]
Explorar las herramientas de
pruebas para la validación de
Azure Functions
En este capítulo, vamos a explorar distintas formas de probar Azure Functions
con mayor detalle con las siguientes recetas:

• Probar Azure Functions:


° Probar los desencadenadores de HTTP mediante Postman
° Probar el desencadenador de blob mediante el explorador
de Microsoft Storage
° Probar el desencadenador de cola mediante el portal de
administración de Azure
• Probar una función de Azure en un entorno preconfigurado mediante
ranuras de implementación
• Realizar pruebas de carga de Azure Functions mediante Azure DevOps
• Crear y probar la función de Azure a nivel local mediante herramientas
de CLI de Azure
• Probar y validar la capacidad de respuesta de la función de Azure mediante
Application Insights
• Desarrollar pruebas unitarias para Azure Functions con desencadenadores
de HTTP

Introducción
En los capítulos anteriores, has descubierto cómo desarrollar Azure Functions
y cuándo pueden resultar útiles. Además, has aprendido a validar la funcionalidad
de dichas funciones.
[ 121 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

En este capítulo, vamos a echar un vistazo a las formas de probar distintas


Azure Functions. Esto incluye, por ejemplo, realizar pruebas de funciones del
desencadenador de HTTP mediante Postman y utilizar el explorador de Microsoft
Storage para probar desencadenadores de blob de Azure, desencadenadores
de cola y otros desencadenadores relacionados con los servicios de
almacenamiento. También vas a aprender a realizar una prueba de carga sencilla
en un desencadenador de HTTP para ayudarte a comprender cómo funciona la
arquitectura sin servidor mediante al aprovisionamiento de las instancias del back-
end sin que los desarrolladores tengan que preocuparse de los ajustes de escalado
con distintos factores. El runtime de Azure Function escalará automáticamente las
instancias.

También descubrirás cómo configurar una prueba que verifique la disponibilidad


de nuestras funciones haciendo ping continuamente a los puntos de conexión de la
aplicación en una frecuencia predefinida desde distintas ubicaciones.

Probar Azure Functions


El runtime de Azure Function nos permite crear e integrar muchos servicios de
Azure. A fecha de redacción del presente documento, existen más de 20 tipos de
Azure Functions que puedes crear. En esta receta, aprenderás a probar las Azure
Functions más comunes, tal como se indica a continuación:

• Probar los desencadenadores de HTTP mediante Postman


• Probar el desencadenador de blob mediante el explorador de Microsoft
Storage
• Probar el desencadenador de cola mediante el portal de administración
de Azure

Preparación
Si no lo has hecho previamente, instala las siguientes herramientas:

• Postman: puedes descargarla en https://www.getpostman.com/


• Explorador de Microsoft Azure Storage: puedes descargarlo en
http://storageexplorer.com/

Puedes usar el explorador de Storage para conectarte a las cuentas de


almacenamiento y ver todos los datos disponibles de distintos servicios de
almacenamiento, como blobs, colas, tablas y archivos. También los puedes
crear, actualizar y eliminar desde el explorador de Storage.

[ 122 ]
Capítulo 5

Cómo hacerlo...
En esta sección, vamos a crear tres Azure Functions con las plantillas
predeterminadas disponibles en el portal de administración de Azure
y, a continuación, las probaremos con diferentes herramientas.

Probar los desencadenadores de HTTP mediante


Postman
Sigue estos pasos:

1. Crea una función de desencadenador de HTTP que acepte los parámetros


Firstname y Lastname y los envíe como respuesta. Cuando se haya creado,
establece el Nivel de autorización como Anónimo.
2. Reemplaza el código predeterminado por el siguiente. Ten en cuenta que
he eliminado las validaciones para facilitar la tarea. En las aplicaciones en
tiempo real, deberás validar todos los parámetros de entrada:
#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req,


ILogger log)
{
log.LogInformation("C# HTTP trigger function processed
a request.");

string firstname=req.Query["firstname"];
string lastname=req.Query["lastname"];

string requestBody = await new StreamReader(req.Body).


ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
firstname = firstname ?? data?.firstname;
lastname = lastname ?? data?.lastname;

return (ActionResult)new OkObjectResult($"Hello,


{firstname + " " + lastname}");

[ 123 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

3. Abre la herramienta Postman y sigue estos pasos:

1. En primer lugar, elige el tipo de método HTTP con el que quieras
realizar la solicitud HTTP. De forma predeterminada, nuestra función
acepta la mayoría de los métodos. Elige el método GET, tal como se
muestra a continuación:

2 El siguiente paso es proporcionar la URL del desencadenador


de HTTP. Ten en cuenta que deberás sustituir
<HttpTriggerTestUsingPostman> por el nombre de tu función
HttpTrigger, tal como se muestra a continuación:

4. Haz clic en el botón Enviar para realizar la solicitud. Si has proporcionado


todos los detalles que espera la API, verás Estado: 200 OK, junto con la
respuesta, tal como se muestra continuación:

[ 124 ]
Capítulo 5

Probar un desencadenador de blob mediante el


explorador de Microsoft Storage
Sigue estos pasos:

1. Para crear un nuevo desencadenador de blob, elige la plantilla de


desencadenador de Azure Blob Storage, tal como se indica a continuación:

2. Cuando hagas clic en la plantilla de la captura de pantalla anterior, se te


pedirá que proporciones una cuenta de almacenamiento y un contenedor en
el que almacenarás el blob, tal como se muestra a continuación:

[ 125 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

3. Vamos a realizar una conexión con la cuenta de almacenamiento que


utilizaremos en esta receta. Abre el explorador de Microsoft Azure Storage
y haz clic en el botón que se destaca en la siguiente captura de pantalla para
conectarte a Azure Storage:

4. Se te pedirá que introduzcas detalles, incluida la cadena de conexión


de almacenamiento, la firma de acceso compartido (SAS) y la clave
de la cuenta. Para esta receta vamos a usar la cadena de conexión de
almacenamiento. Dirígete a Cuenta de almacenamiento, copia la cadena
de conexión de la hoja Claves de acceso y pégala en la ventana emergente
Explorador de Microsoft Azure Storage - Conectar, tal como se indica
a continuación:

[ 126 ]
Capítulo 5

5. Al hacer clic en el botón Siguiente de la captura de pantalla anterior,


accederás a la ventana Resumen de la conexión, que muestra el nombre de
la cuenta y otra información relacionada para su confirmación. Haz clic en el
botón Conectar para conectarte a la cuenta de Azure Storage que decidas.
6. Como se muestra en la siguiente captura de pantalla, ya estás conectado a la
cuenta de Azure Storage, desde la que podrás gestionar todos los servicios de
Azure Storage:

7. Vamos a crear un contenedor de almacenamiento denominado samples-


workitems. Haz clic con el botón derecho en la carpeta Contenedores de
blobs y, a continuación, en Crear contenedor de blobs para crear un nuevo
contenedor de blobs denominado samples-workitems. Haz clic en el botón
Cargar archivos, tal como se muestra en la siguiente captura de pantalla:

8. En la ventana Cargar archivos, selecciona el archivo que quieras subir y haz


clic en el botón Cargar.

[ 127 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

9. Inmediatamente después, ve al editor de código de la función de Azure


y echa un vistazo a la ventana Registros, tal como se muestra en la
siguiente captura de pantalla. El registro indica que la función de Azure se
desencadena correctamente:

Probar el desencadenador de cola mediante el


portal de administración de Azure
Sigue estos pasos:

1. Crea un nuevo desencadenador de cola de Azure Storage denominado


QueueTriggerTestusingPortal, tal como se muestra en la siguiente
captura de pantalla. Anota el nombre de la cola, myqueue-items, ya que
posteriormente deberemos crear un servicio de cola con el mismo nombre
mediante el portal de administración de Azure:

[ 128 ]
Capítulo 5

2. Dirígete a la hoja Información general de la cuenta de almacenamiento y haz


clic en Colas, tal como se muestra en la siguiente captura de pantalla:

3. En la hoja Servicio de cola, haz clic en Cola para añadir una cola nueva:

4. Escribe myqueue-items en el Nombre de cola en la ventana emergente


Agregar a la cola, tal como se muestra en la siguiente captura de pantalla. Se
trata del mismo nombre que usamos al crear el desencadenador de cola. Haz
clic en Aceptar para crear el servicio de cola:

[ 129 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

5. Ahora vamos a crear un mensaje de cola. En el portal de administración de


Azure, haz clic en el servicio de cola myqueue-items para acceder a la hoja
Mensajes. Haz clic en el botón Agregar mensaje, tal como se indica en la
siguiente captura de pantalla. Escribe el texto para el mensaje de cola. Por
último, haz clic en Aceptar para crear el mensaje de cola:

6. Inmediatamente después, dirígete al desencadenador de cola


QueueTriggerTestusingPortal y revisa la hoja Registros. En ella podrás
descubrir cómo se ha desencadenado la función de cola, tal como se muestra
en la siguiente captura de pantalla:

[ 130 ]
Capítulo 5

Y eso no es todo…
Para todos los desencadenadores de HTTP, si quieres que los clientes de la API solo
utilicen el método POST, restríngelo. Para ello, elige Métodos seleccionados y solo
POST en Métodos HTTP seleccionados, tal como se muestra en la siguiente captura
de pantalla:

Probar una función de Azure en un


entorno preconfigurado mediante
ranuras de implementación
En general, todas las aplicaciones necesitan entornos de preproducción, como
ensayos, betas, etc., para revisar las funcionalidades antes de publicarlas para los
usuarios finales.

Aunque los entornos de preproducción son fantásticos y ayudan a las partes


interesadas a validar la funcionalidad de la aplicación en relación con los requisitos
empresariales, también pueden ser difíciles de gestionar y mantener. A continuación,
se muestran algunos de estos puntos débiles:

• Tendríamos que crear y utilizar un entorno independiente para nuestros


entornos de preproducción.
• Cuando todo se hubiese revisado en preproducción y el equipo de
operaciones de TI recibiese la aprobación, habría un tiempo de inactividad
en el entorno de producción al implementar el código base de nuevas
funcionalidades.

[ 131 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

Las limitaciones anteriores se pueden cubrir en Azure Functions mediante una


función denominada ranuras (se denominan ranuras de implementación en
los entornos de App Service). Con las ranuras puedes configurar un entorno de
preproducción en el que puedes revisar las nuevas funcionalidades y promover su
paso (mediante el intercambio, que comentaremos en un momento) al entorno de
producción sin problemas y cuando lo necesites.

Cómo hacerlo...
Sigue estos pasos:

1. Crea una nueva aplicación de función denominada MyProductionApp.


2. Crea un nuevo desencadenador de HTTP y llámalo MyProd-HttpTrigger1.
Sustituye la última línea por lo siguiente:
return name != null
? (ActionResult)new OkObjectResult("Welcome to MyProd-
HttpTrigger1 of Production App")
: new BadRequestObjectResult("Please pass a name on the
query string or in the request body");

3. Crea otro desencadenador de HTTP y llámalo MyProd-HttpTrigger2. Usa


el mismo código que para MyProd-HttpTrigger1 y sustituye la última línea
por lo siguiente:
return name != null
? (ActionResult)new OkObjectResult("Welcome to MyProd-
HttpTrigger2 of Production App")
: new BadRequestObjectResult("Please pass a name on the
query string or in the request body");

4. Supongamos que ambas funciones de la aplicación de función están activas


en el entorno de producción con la URL https://<<functionappname.
azurewebsites.net>>.
5. El cliente nos ha pedido que modifiquemos ambas funciones. En lugar de
aplicar directamente los cambios a las funciones de la aplicación de función
de producción, es posible que debas crear una ranura.
6. ¡Cuidado! Antes de crear una ranura, deberás activar la función. Para ello,
dirígete a Configuración de la aplicación de función en Configuración
general de la pestaña Características de la plataforma de la aplicación de
función. Cuando hagas clic en la configuración de la aplicación de función,
se abrirá una nueva pestaña en la que podrás activar Ranuras (Preview), tal
como se muestra en la siguiente captura de pantalla:

[ 132 ]
Capítulo 5

La función de ranuras está en versión preview. Cuando leas esto, es


posible que haya pasado a Disponible con carácter general (GA). No
se recomienda utilizar esta función en cargas de trabajo de producción
hasta que pase a estar GA.

7. Haz clic en el botón de activación en la sección Ranuras (Preview) que se


destaca en la captura de pantalla previa. Cuando pulses este botón, la sección
de ranuras se ocultará, ya que se trata de una configuración puntual. Una vez
activada, no podrás desactivarla.
8. Vamos a crear una nueva ranura con todas las funciones que tenemos en
nuestra aplicación de función, denominada MyProductionApp.
9. Haz clic en el icono +, disponible cerca de la sección Ranuras (Preview), tal
como se muestra en la siguiente captura de pantalla:

10. Se te pedirá que introduzcas un nombre para la nueva ranura. Proporciona


un nombre descriptivo, como Ensayo, tal como se muestra en la siguiente
captura de pantalla:

[ 133 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

11. Cuando hagas clic en Crear, se creará una nueva ranura, tal como se indica
en la siguiente captura de pantalla. En este caso, si Functions es de solo
lectura, puedes cambiar a lectura y escritura en la configuración de la
aplicación de función.

La URL de la ranura será https://<<functionappname>>-


<<Slotname>>.azurewebsites.net>>. Cada ranura de la aplicación
de función tendrá una URL diferente.

12. Para que un entorno preconfigurado esté completo, deberás copiar todas las
Azure Functions desde el entorno de producción (en este caso, la aplicación
MyProductionApp) en la nueva ranura preconfigurada denominada Ensayo.
Crea dos desencadenadores de HTTP y copia el código de ambas funciones
(MyProd-HttpTrigger1 y MyProd-HttpTrigger2) de MyProductionApp a la
nueva ranura Ensayo. Básicamente, deberás copiar manualmente todas las
funciones en la nueva ranura.
13. Cambia la cadena producción por ensayo en la última línea de ambas
funciones de la ranura Ensayo. Esto resultará útil para probar el resultado
de la operación de intercambio:

[ 134 ]
Capítulo 5

Ten en cuenta que, en todas las ranuras que crees como aplicación de
preproducción, deberás asegurarte de utilizar los mismos nombres de
función que tienes en el entorno de producción.

14. Haz clic en el botón Intercambiar, disponible en la hoja Ranuras de


implementación, tal como se muestra en la siguiente captura de pantalla:

15. En la hoja Intercambiar, deberás elegir lo siguiente:


° Tipo de intercambio: selecciona la opción Intercambiar.
° Origen: selecciona la ranura que quieras trasladar a producción.
En este caso vamos a intercambiar Ensayo en general, pero se
puede realizar el intercambio incluso entre ranuras que no sean
de producción.

[ 135 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

° Destino: selecciona la opción producción, tal como se muestra en la


siguiente captura de pantalla:

16. Cuando revises la configuración, haz clic en el botón Aceptar del paso
anterior. Se tardará unos minutos en intercambiar las funciones. Aparecerá
una barra de progreso, tal como se muestra en la siguiente captura
de pantalla:

[ 136 ]
Capítulo 5

17. Transcurrido un minuto o dos, las ranuras de ensayo y producción se


intercambiarán. Vamos a revisar los archivos de script run.csx de la
producción:

18. Si no ves ningún cambio, haz clic en el botón de actualización de la aplicación


de función, tal como se muestra en la siguiente captura de pantalla:

[ 137 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

19. Asegúrate de que Configuración de la aplicación y Cadenas de conexión


a base de datos se marcan como Configuración de ranuras (específico de
ranura). De lo contrario, Configuración de la aplicación y Cadenas de
conexión a base de datos también se intercambiarán, lo que podría provocar
un comportamiento inesperado. Puedes marcar cualquiera de estos ajustes
desde Características de la plataforma, tal como se muestra en la siguiente
captura de pantalla:

20. Al hacer clic en Configuración de la aplicación accederás a la siguiente hoja,


en la que podrás marcar cualquier ajuste como CONFIGURACIÓN DE
RANURAS:

Todas las funciones de la receta son desencadenadores de HTTP. Ten


en cuenta que puedes tener cualquier tipo de desencadenador en la
aplicación de función. Las ranuras de implementación no se limitan a los
desencadenadores de HTTP.
Puede tener múltiples ranuras para cada una de las aplicaciones de
función. A continuación, se muestran unos ejemplos:
Alfa
Beta
Ensayo
[ 138 ]
Capítulo 5

Y eso no es todo…
Si intentas crear una ranura sin habilitar la función Ranuras de implementación,
verás algo similar a lo que se muestra en la siguiente captura de pantalla:

Debes tener todas las Azure Functions en todas las ranuras que quieras intercambiar
con la aplicación de función de producción:

• Las ranuras son específicas de la aplicación de función, pero no de la función


individual.
• Cuando hayas habilitado las ranuras, se regenerarán todas las claves,
incluida la maestra. Ten cuidado si ya has compartido las claves de las
funciones con terceros. Si ya las habías compartido y habilitado las ranuras,
las integraciones existentes con las claves antiguas no funcionarán.

En general, si utilizas App Services y quieres crear ranuras de implementación, debes


tener un plan de App Service en el nivel Estándar o Premium. Sin embargo, puedes
crear ranuras para la aplicación de función incluso con los planes de consumo
(o dinámicos).

Realizar pruebas de carga de Azure


Functions mediante Azure DevOps
Todas las aplicaciones deben tener un rendimiento adecuado. Es responsabilidad
de todos los miembros del equipo que la aplicación funcione correctamente. En esta
receta, aprenderás a crear una carga en Azure Functions mediante la herramienta
Prueba de carga de Azure DevOps (anteriormente conocido como VSTS). Esta
receta también te ayudará a comprender cómo funciona el escalado automático
de instancias en el entorno sin servidor, sin necesidad de que los desarrolladores
o el arquitecto se preocupen por las instancias responsables de responder a las
solicitudes.

[ 139 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

Preparación
Crea una cuenta de Azure DevOps en https://visualstudio.microsoft.com/.
Vamos a utilizar la herramienta Prueba de carga de Azure DevOps para crear
pruebas de carga basadas en URL.

Cómo hacerlo...
Sigue estos pasos:

1. Crea un nuevo desencadenador de HTTP denominado


LoadTestHttpTrigger, cuyo Nivel de autorización sea Anónimo.
2. Reemplaza el código predeterminado en run.csx por el siguiente:
using System.Net;
using Microsoft.AspNetCore.Mvc;
public static async Task<IActionResult> Run(HttpRequest req,
ILogger log)
{
System.Threading.Thread.Sleep(2000);
return (ActionResult)new OkObjectResult($"Hello");
}

3. El código anterior es evidente. Para que la prueba de carga resulte


interesante, vamos a simular la carga de procesamiento. Para ello,
añadiremos un tiempo de espera de dos segundos, mediante System.
Threading.Thread.Sleep(2000);.
4. Copia la URL de la función. Para ello, haz clic en el enlace </> Obtener la
dirección URL de la función de la parte derecha del editor de código de
run.csx.
5. Dirígete a la pestaña Prueba de carga de la cuenta de Azure DevOps. La
encontrarás en el menú de prueba tras iniciar sesión en Azure DevOps:

[ 140 ]
Capítulo 5

6. Haz clic en el enlace Nuevo y selecciona Prueba basada en dirección URL,


tal como se muestra en la siguiente captura de pantalla:

7. En la pestaña Escenarios web, proporciona un nombre significativo para


la prueba de carga, tal como se muestra en la siguiente captura de pantalla:

8. Pega la URL del desencadenador de HTTP que has copiado en el paso 4


en el campo de entrada de la URL, tal como se muestra en la siguiente
captura de pantalla:

[ 141 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

9. Haz clic en el botón Guardar para guardar la prueba de carga:

10. El siguiente paso es proporcionar detalles sobre la carga que queremos crear
en la función de Azure. Como se indica en la siguiente captura de pantalla,
haz clic en Configuración y proporciona información sobre la prueba de
carga que desees en función de tus requisitos:

[ 142 ]
Capítulo 5

11. Cuando suministres toda la información de la prueba de carga, haz clic en


Guardar. Al guardar la prueba, el botón Ejecutar prueba se activará, tal
como se muestra en la siguiente captura de pantalla:

12. Haz clic en Ejecutar prueba para iniciar la prueba de carga. Dado que la
duración de la ejecución de nuestra prueba de carga es de 20 minutos, se
tardará 20 minutos en completarla. Cuando la carga se haya completado,
Azure DevOps proporcionará los informes de rendimiento, tal como se
indica a continuación:
° Informe de resumen: esta opción proporciona el tiempo medio de
respuesta del desencadenador de HTTP para una carga de 1000
usuarios.

Y eso no es todo…
También podemos consultar cómo Azure se amplía automáticamente en segundo
plano en la pestaña Live Metrics Stream de Application Insights. La siguiente
captura de pantalla muestra los identificadores de instancia y el estado de las
máquinas virtuales que se asignan automáticamente, en función de la carga en la
arquitectura sin servidor de Azure. Descubrirás cómo integrar Application Insights
con Azure Functions en el capítulo 6, Supervisar y solucionar problemas de servicios de
Azure sin servidor

[ 143 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

Consulta también
La receta de supervisión de Azure Functions mediante Application Insights del
capítulo 6, Supervisar y solucionar problemas de servicios de Azure sin servidor, contiene
más información sobre este tema.

Crear y probar Azure Functions a nivel


local mediante herramientas de CLI
de Azure
La mayoría de las recetas que has aprendido se han creado mediante el navegador
o el Entorno de desarrollo integrado (IDE de Visual Studio).

Azure también nos proporciona herramientas para los desarrolladores que disfrutan
al trabajar con la línea de comandos. Estas herramientas nos permiten crear recursos
de Azure con comandos sencillos directamente desde la línea de comandos. En esta
receta, aprenderás a crear una nueva aplicación de función y comprenderás cómo
crear una función e implementarla en el cloud de Azure desde la línea de comandos.

[ 144 ]
Capítulo 5

Preparación
Sigue estos pasos:

• Descarga e instala Node.js desde https://nodejs.org/en/download/.


• Descarga e instala las herramientas de Azure CLI desde https://docs.
microsoft.com/cli/azure/install-azure-cli?view=azure-cli-
latest.

Cómo hacerlo...
Sigue estos pasos:

1. Cuando las Azure Functions Core Tools estén preparadas, ejecuta el


siguiente comando para crear una nueva aplicación de función:
func init

Tras ejecutar el comando anterior, obtendrás el siguiente resultado:

[ 145 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

En la captura de pantalla anterior, dotnet está seleccionado de forma


predeterminada. Si pulsas Intro, se crearán los archivos necesarios, tal como
se muestra en la siguiente captura de pantalla:

2. Ejecuta el siguiente comando para crear una nueva función de


desencadenador de HTTP con la nueva aplicación de función que hemos
creado:
func new

Tras ejecutar el comando anterior, obtendrás el siguiente resultado:

3. Tal como se indica en la captura de pantalla anterior, se te pedirá que elijas


la plantilla de función. Para esta receta, he elegido HttpTrigger. Elige
HttpTrigger mediante la flecha abajo. Puedes elegir el tipo de función
de Azure en base a tus requisitos. Navega por las opciones con las flechas
arriba/abajo del teclado.

[ 146 ]
Capítulo 5

4. El siguiente paso es proporcionar un nombre a la función de Azure que


vas a crear. Proporciona un nombre descriptivo y pulsa Intro, tal como se
muestra en la siguiente captura de pantalla:

5. Puedes utilizar tu IDE favorito para editar el código de función de Azure. En


esta receta, voy a usar Visual Studio Code para abrir la función HttpTrigger,
tal como se muestra en la siguiente captura de pantalla:

6. Vamos a probar la función de Azure directamente desde el equipo local. Para


ello, debemos iniciar el host de la función de Azure mediante la ejecución del
siguiente comando:
func host start --build

[ 147 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

7. Cuando el host se haya iniciado, podrás copiar la URL y probarla en tu


navegador, junto con un nombre de parámetro de cadena de consulta, tal
como se muestra en la siguiente captura de pantalla:

Probar y validar la capacidad de


respuesta de la función de Azure
mediante Application Insights
Cualquier aplicación es útil para la empresa si funciona correctamente. Las
aplicaciones pueden dejar de funcionar por muchas razones. A continuación, se
muestran algunas:

• Aunque sería muy raro, podrían producirse errores de hardware, como


bloqueos del servidor, errores del disco duro o cualquier otro problema,
incluso el centro de datos podría dejar de funcionar.
• Puede haber errores de software debido a un código incorrecto o a un error
de implementación.
• El sitio puede recibir un tráfico inesperado y es posible que los servidores no
sean capaces de gestionarlo.
• Puede suceder que la aplicación sea accesible en un país y no en otros.

Nos resultaría muy útil recibir una notificación cuando el sitio no esté disponible
o no responda a las solicitudes de los usuarios. Azure proporciona unas cuantas
herramientas para alertarnos si el sitio web no responde o no está disponible. Una
de ellas es Application Insights. Aprenderás a configurar Application Insights para
hacer ping a nuestra aplicación de función de Azure cada minuto y ajustarla para
que nos avise si la función no responde.

[ 148 ]
Capítulo 5

Preparación
Sigue estos pasos:

1. Dirígete al portal de administración de Azure, busca Application Insights,


haz clic en el botón Crear y proporciona la información necesaria, tal como se
muestra en la siguiente captura de pantalla:

[ 149 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

2. Ve a la hoja Información general de la aplicación de función y echa un


vistazo a la URL de la aplicación de función, tal como se muestra en la
siguiente captura de pantalla:

Cómo hacerlo...
Sigue estos pasos:

1. Dirígete a la hoja Disponibilidad y haz clic en el botón Agregar, tal como se


muestra en la siguiente captura de pantalla:

[ 150 ]
Capítulo 5

2. En la hoja Crear prueba, escribe un nombre descriptivo para el requisito


y pega la URL de la aplicación de función, que anotaste en el paso 2 de la
sección Preparación anterior, en el campo URL de la hoja Crear prueba.
En la hoja Alertas, proporciona una dirección de correo electrónico en el
campo Enviar alertas por correo electrónico a estas direcciones de correo
electrónico: a las que se enviará una alerta si la función no está disponible
o no responde.

[ 151 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

3. Haz clic en Aceptar en la hoja Alertas y, a continuación, haz clic en el botón


Crear en la hoja Crear prueba para crear la prueba, tal como se muestra
en la siguiente captura de pantalla, en la sección Todas las pruebas de
disponibilidad:

4. Para probar la funcionalidad de esta alerta, vamos a detener la aplicación de


función. Para ello, haz clic en el botón Detener de la pestaña Información
general de la aplicación de función.

[ 152 ]
Capítulo 5

5. Cuando la aplicación de función se detenga, Application Insights intentará


acceder a la URL de la función mediante la prueba de ping. El código de
respuesta no será 200, ya que la aplicación se ha detenido, lo que significa
que la prueba no se ha superado y que debería haberse enviado una
notificación al correo electrónico configurado, tal como se muestra en la
siguiente captura de pantalla:

Cómo funciona...
Hemos creado una prueba de Disponibilidad en la que se hará ping en nuestra
aplicación de función cada cinco minutos desde un máximo de cinco ubicaciones
diferentes de todo el mundo. Puedes configurarlas en la pestaña Ubicación de
la prueba de la hoja Crear prueba al crear la prueba. El criterio predeterminado
del ping es comprobar si el código de respuesta de la URL es 200. Si el código de
respuesta no es 200, la prueba habrá fallado y se enviará una alerta a la dirección de
correo electrónico configurable.

Y eso no es todo…
Puedes utilizar una prueba web de varios pasos (con la opción Tipo de prueba de
la hoja Crear prueba) si quieres probar una página o funcionalidad que requiera la
navegación por distintas páginas.

Desarrollar pruebas unitarias para


Azure Functions con desencadenadores
de HTTP
Hasta ahora, hemos creado varias Azure Functions y validado su funcionalidad con
distintas herramientas. Las funcionalidades de las funciones que hemos desarrollado
hasta ahora son bastante simples. Sin embargo, en las aplicaciones reales, no será
tan sencillo, ya es probable que se tengan que aplicar muchos cambios al código que
creamos inicialmente. Se recomienda escribir pruebas unitarias automatizadas que
nos ayuden a probar la funcionalidad de nuestras Azure Functions. Cada vez que
ejecutemos estas pruebas unitarias automatizadas, podremos probar las diferentes
rutas dentro del código.
[ 153 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

En esta receta, aprenderemos a utilizar el desencadenador de HTTP y descubriremos


lo sencillo que es escribir casos de pruebas unitarias automatizadas con el Explorador
de pruebas de Visual Studio y Moq (un marco de código abierto disponible como
paquete NuGet).

Preparación
Vamos a utilizar el marco de simulación de Moq para realizar una prueba unitaria de
nuestra función de Azure. Para esta receta, es necesario un conocimiento básico del
funcionamiento de Moq. Si lo necesitas, puedes obtener más información sobre Moq
en https://github.com/moq/moq4/wiki.

Para que el caso de prueba unitaria sea más sencillo, he comentado las líneas
de código que leen los datos de los parámetros Post del método Run del
desencadenador de HTTP HTTPTriggerCSharpFromVS, tal como se muestra a
continuación destacado en negrita.
[FunctionName("HTTPTriggerCSharpFromVS")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post",
Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed
a request.");

string name = req.Query["name"];

//string requestBody = await new StreamReader(req.Body).


ReadToEndAsync();
//dynamic data = JsonConvert.
DeserializeObject(requestBody);
//name = name ?? data?.name;

return name != null


? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on
the query string or in the request body");
}

[ 154 ]
Capítulo 5

Cómo hacerlo...
Sigue estos pasos:

1. Crea un nuevo proyecto de pruebas unitarias. Para ello, haz clic con el botón
derecho en la solución y, a continuación, haz clic en Agregar nuevo proyecto.
En la ventana Agregar nuevo proyecto, selecciona Prueba en la lista de Tipo
de proyecto y xUnit Test Project(.NET Core) en la lista de proyectos tal
como se indica a continuación:

2. Asegúrate de seleccionar xUnit Test Project(.NET Core) en la consola


Administrador de paquetes y ejecuta los siguientes comandos:
°° Instala el paquete Moq NuGet mediante el comando Install-
Package Moq.
°° Instala el paquete ASP.NET Core mediante el comando Install-
Package Microsoft.AspNetCore.
3. En el proyecto de pruebas unitarias, también necesitamos la referencia a la
función de Azure para la que queremos ejecutar las pruebas unitarias. Añade
una referencia a la aplicación FunctionAppInVisualStudio para poder
llamar al método Run del desencadenador de HTTP desde nuestras pruebas
unitarias.

[ 155 ]
Explorar las herramientas de pruebas para la validación de Azure Functions

4. Añade los espacios de nombres necesarios a la clase Prueba unitaria


como se muestra a continuación y sustituye el código predeterminado por
el siguiente. El siguiente código simula las solicitudes, crea una colección
de cadenas de consulta con una clave denominada name, asigna el valor
Praveen Sreeram, ejecuta la función, obtiene la respuesta y compara el valor
de respuesta con un valor esperado:
using FunctionAppInVisualStudio;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.Primitives;
using Moq;
using System;
using System.Collections.Generic;
using Xunit;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace AzureFunctions.Tests
{
public class ShouldExecuteAzureFunctions
{
[Fact]
public async Task WithAQueryString()
{
var httpRequestMock = new Mock<HttpRequest>();
var LogMock = new Mock<ILogger>();
var queryStringParams = new Dictionary<String,
StringValues>();
httpRequestMock.Setup(req => req.Query).Returns(new Qu
eryCollection(queryStringParams));
queryStringParams.Add("name", "Praveen Sreeram");

var result = await HTTPTriggerCSharpFromVS.


Run(httpRequestMock.Object,LogMock.Object);
var resultObject = (OkObjectResult)result;
Assert.Equal("Hello, Praveen Sreeram", resultObject.
Value);
}
}
}

[ 156 ]
Capítulo 5

5. Haz clic con el botón derecho en la prueba unitaria y haz clic en Ejecutar
prueba, tal como se muestra en la siguiente captura de pantalla:

Si todo se ha configurado correctamente, las pruebas deberían superarse, tal como se


muestra en la siguiente captura de pantalla:

Eso es todo. Hemos aprendido a escribir un caso de prueba unitaria básica para un
desencadenador de HTTP.

[ 157 ]
Supervisar y solucionar
problemas de los servicios de
Azure sin servidor
En este capítulo, vas a aprender lo siguiente:

• Solucionar problemas de Azure Functions


• Integrar Azure Functions con Application Insights
• Supervisar Azure Functions
• Insertar datos de telemetría personalizados en Application Insights Analytics
• Enviar datos de telemetría de la aplicación por correo electrónico
• Integrar datos de supervisión de Application Insights en tiempo real con
Power BI mediante Azure Functions

Introducción
El proceso de implementación no termina cuando se completa el desarrollo de un
proyecto y se lanza una aplicación. Debemos supervisar continuamente nuestras
aplicaciones, analizar su rendimiento y revisar los registros para determinar si el
usuario final está experimentando problemas.

Azure nos proporciona diversas herramientas para satisfacer todos nuestros


requisitos de supervisión, directamente desde las fases de desarrollo
y mantenimiento.

En este capítulo, vas a aprender a utilizar estas herramientas y a tomar las medidas
necesarias en función de la información disponible.

[ 158 ]
Capítulo 6

Solucionar problemas de Azure


Functions
En esta receta, vas a aprender a ver los registros de aplicación de las aplicaciones
de funciones mediante la característica de secuencias de registro de las funciones.

Cómo hacerlo...
Una vez desarrolladas y probadas tus aplicaciones en el entorno local, puedes
intentar implementarlas en Azure. Puede haber casos en los que surjan problemas
después de implementar una aplicación en Azure, ya que el entorno es diferente.
Por ejemplo, es posible que un desarrollador no haya creado la configuración
de la aplicación en la aplicación. Si falta una clave de configuración, es posible
que la aplicación no funcione de la forma prevista y no es fácil solucionar el
error. Afortunadamente, el entorno de Azure facilita esta resolución gracias a la
característica de secuencias de registro. En esta receta, vamos a aprender a ver los
registros en tiempo real y a utilizar la función Diagnosticar y solucionar problemas.

Ver registros de aplicaciones en tiempo real


Sigue estos pasos:
1. Ve a Características de la plataforma de la aplicación de la función y haz
clic en el botón Secuencias de registro, donde podrás ver los Registros de
aplicación, tal como se muestra en la captura de pantalla siguiente:

En el momento en que se redactó esta receta, los registros


del servidor web no contenían información relativa a Azure
Functions.

[ 159 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

2. Vamos a abrir cualquiera de las Azure Functions que hayas agregado


anteriormente en una nueva pestaña del explorador y a agregar una línea de
código que genere una excepción. Para que resulte sencillo (y simplemente
para ilustrar cómo funcionan los registros de aplicación de la secuencia de
registros), he agregado la línea siguiente al desencadenador de HTTP simple
creado anteriormente:

3. A continuación, haz clic en el botón Guardar y luego en el botón Ejecutar. Tal


como estaba previsto, recibirás una excepción, junto con el mensaje de la sección
Registros de aplicación que se muestra en la siguiente captura de pantalla:

La ventana de registro muestra los errores solo para esa función concreta,
no para las demás funciones asociadas a la aplicación de funciones. Es
en este caso en el que resultan útiles los registros de las aplicaciones de
secuencias de registro, que se pueden utilizar para todas las funciones de
cualquier aplicación de funciones.

[ 160 ]
Capítulo 6

Diagnosticar la aplicación de funciones completa


En la sección anterior, hemos aprendido a supervisar los errores de la aplicación
en tiempo real, lo que resulta útil para identificar y corregir rápidamente cualquier
problema. Sin embargo, no siempre es posible supervisar los registros de aplicación
y comprender los errores que los usuarios finales podrían estar experimentando.
Azure Functions proporciona otra excelente herramienta, denominada Diagnosticar
y solucionar problemas:
1. Ve a Características de la plataforma y haz clic en Diagnosticar y solucionar
problemas, como se muestra en la siguiente captura de pantalla:

2. Poco después, se abrirá otra hoja, donde puedes seleccionar la categoría


adecuada para los problemas que estés tratando de solucionar en ese
momento. Haz clic Todos los errores 5xx para ver los detalles sobre las
excepciones que estén experimentando los usuarios finales, tal como se
muestra en la captura de pantalla siguiente:

[ 161 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

3. A continuación, se abrirá la opción Disponibilidad de funciones


y rendimiento y, dentro de esta, verás Bloqueos de aplicación. Haz clic en
la opción Disponibilidad de funciones y rendimiento para ver los enlaces
reales, como se muestra en la siguiente captura de pantalla:

4. Haz clic en Ejecuciones de la función y errores para ver las excepciones


detalladas, como se muestra en la siguiente captura de pantalla:

Y eso no es todo…
Cada evento de función se registra en un servicio de Almacenamiento
de tablas de Azure. Cada mes, se crea una tabla con el nombre
AzureWebJobsHostLogs<año><mes>.

[ 162 ]
Capítulo 6

Como parte de la solución de problemas, si deseas obtener más detalles sobre


cualquier error, busca primero el campo Id. en la sección Detalles de la invocación,
como se muestra en la siguiente captura de pantalla:

Busca esos datos en la columna RowKey de la tabla


AzureWebJobsHostLogs<año><mes>, como se muestra en la siguiente captura
de pantalla:

Como se muestra en la captura de pantalla anterior, obtendrás la entrada de registro


almacenada en el Almacenamiento de tablas. Al hacer clic en la fila, se abrirán todos
los datos del error, como se muestra en la siguiente captura de pantalla:

[ 163 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

Integrar Azure Functions con Application


Insights
Application Insights es un servicio de administración del rendimiento de
aplicaciones. Una vez que integres Application Insights en la aplicación, comenzará
a enviar datos de telemetría a tu cuenta de Application Insights, alojada en el cloud.
En esta receta, aprenderás lo fácil que es integrar Azure Functions con Application
Insights.

Preparación
Hemos creado una cuenta de Application Insights en la receta Probar y validar la
capacidad de respuesta de Azure Functions mediante Application Insights del capítulo 5,
Explorar herramientas de prueba para la validación de Azure Functions. Sigue estos pasos
para crear una cuenta si aún no lo has hecho:
1. Ve al portal de Administración de Azure, haz clic en Crear un recurso
y, a continuación, selecciona Herramientas de administración.
2. Selecciona Application Insights y proporciona todos los datos necesarios.
Si ya has creado una cuenta de Application Insights en la receta anterior,
puedes omitir este paso.
[ 164 ]
Capítulo 6

Cómo hacerlo...
Sigue estos pasos:

1. Una vez creada la cuenta de Application Insights, abre la pestaña


Información general y ve a Clave de instrumentación, como se muestra en
la siguiente captura de pantalla:

2. Ve a Function Apps para seleccionar las aplicaciones para las que deseas
habilitar la supervisión y ve a Configuración de la aplicación.
3. Agrega una nueva clave con el nombre APPINSIGHTS_INSTRUMENTATIONKEY
y proporciona la clave de instrumentación que has copiado de la cuenta
de Application Insights, tal como se muestra a continuación, y haz clic en
Guardar para guardar los cambios:

4. Eso es todo; puedes empezar a utilizar todas las características de


Application Insights para supervisar el rendimiento de las Azure Functions.
Abre Application Insights y la función RegisterUser en dos pestañas
diferentes para probar cómo funciona Live Metrics Stream:
°° Abre Application Insights y haz clic en Live Metrics Stream en la
primera pestaña del navegador, como se muestra en la siguiente
captura de pantalla:

[ 165 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

°° Abre cualquier función de Azure (en mi caso, he abierto el


desencadenador de HTTP) en otra pestaña y ejecuta algunas pruebas
para asegurarte de que emite algunos registros en Application
Insights.

5. Una vez realizadas las pruebas, ve a la pestaña que contiene Application


Insights. Debería verse el tráfico dinámico existente en la aplicación de la
función, como se muestra en la siguiente captura de pantalla:

[ 166 ]
Capítulo 6

Cómo funciona...
Hemos creado una cuenta de Application Insights. Una vez que integres la Clave
de instrumentación de Application Insights con Azure Functions, el runtime
se encargará de enviar los datos de telemetría asincrónicamente a tu cuenta de
Application Insights.

Y eso no es todo…
En Live Metrics Stream, también se pueden ver todas las instancias, junto con otros
datos, como el número de solicitudes por segundo administradas por las instancias.

Supervisar Azure Functions


Ahora ya sabemos cómo integrar Azure Functions con Application Insights.
A continuación, vamos a aprender cómo se ven los registros que se escriben en
Application Insights mediante el código de Azure Functions para que, como
desarrollador, puedas solucionar las excepciones que se produzcan.

Vamos a realizar un pequeño cambio en la función de desencadenador de HTTP


y, a continuación, lo ejecutaremos varias veces.

Cómo hacerlo...
Sigue estos pasos:

1. Ve al desencadenador de HTTP que has creado y reemplaza el código


siguiente. Acabo de mover la línea de código que registra la información a la
consola de registros y he agregado el parámetro name al final del método:
public static async Task<IActionResult> Run(HttpRequest req,
ILogger log)
{
string name = req.Query["name"];
string requestBody = await new
StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.
DeserializeObject(requestBody);
name = name ?? data?.name;
log.LogInformation($"C# HTTP trigger function processed
a request with the input value {name}");
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on
the query string or in the request body");
}

[ 167 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

2. Ahora, ejecuta la función proporcionando el valor del parámetro name con


valores diferentes, como Azure Test Run 1, Azure Test Run 2 y Azure
Test Run 3. Esto es solo para fines de demostración. Puedes usar la entrada
que desees. La consola de registros mostrará el siguiente resultado:

3. Los registros de la consola de registros anterior solo están disponibles


cuando se está conectado a la consola de registros. No estarán disponibles si
no hay conexión. En estos casos es cuando resulta útil Application Insights.
Ve a la instancia de Application Insights que has integrado con la aplicación
de la función de Azure.
4. Haz clic en el botón Análisis que está disponible en la pestaña Información
general de Application Insights, como se muestra en la siguiente captura
de pantalla:

[ 168 ]
Capítulo 6

5. En la ventana de consulta de análisis, escribe el comando traces | sort by


timestamp desc, que devuelve todos los seguimientos ordenados por fecha
descendente, como se muestra en la siguiente captura de pantalla:

Cómo funciona...
En el desencadenador de HTTP, hemos agregado una instrucción de registro que
muestra el valor del parámetro name proporcionado por el usuario. Hemos ejecutado
el desencadenador de HTTP varias veces. Transcurridos unos instantes, haz clic en
el botón Análisis del botón Application Insights, lo que abrirá la ventana Análisis,
donde puedes escribir consultas para ver los datos de telemetría emitidos por Azure
Functions. Todo esto se puede llevar a cabo sin necesidad de escribir ningún código
personalizado.

Insertar datos de telemetría


personalizados en Application Insights
Analytics
Nuestros clientes te han pedido que proporciones informes de análisis para una
métrica derivada dentro de Application Insights. Pero ¿qué es una métrica derivada?
Pues bien, de forma predeterminada, Application Insights te proporciona abundante
información sobre métricas, como solicitudes, errores, excepciones, etcétera.
Puedes ejecutar consultas en la información que Application Insights proporciona
utilizando su lenguaje de consulta de análisis.

[ 169 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

En este contexto, solicitudes por hora es una métrica derivada y, si deseas


compilar un nuevo informe dentro de Application Insights, tendrás que proporcionar
datos a Application Insights sobre la nueva métrica derivada de forma periódica.
Una vez que proporciones los datos requeridos periódicamente, Application Insights
se encargará de proporcionar informes para que los analices.

Vamos a usar Azure Functions que proporcionan datos a Application Insights con
una métrica derivada denominada solicitudes por hora:

Para este ejemplo, vamos a desarrollar una consulta mediante el lenguaje de consulta
de análisis para la métrica derivada solicitudes por hora. Puedes realizar
cambios en la consulta para generar otras métricas derivadas para tus requisitos,
como, por ejemplo, solicitudes por hora para mi campaña o una métrica similar.

Puedes obtener más información sobre el lenguaje de consulta de


análisis en https://docs.microsoft.com/en-us/azure/
application-insights/app-insights-analytics-
reference.

[ 170 ]
Capítulo 6

Preparación
Sigue estos pasos de requisitos previos:

1. Crea una cuenta de Application Insights nueva si aún no tienes una.


2. Asegúrate de que tienes una aplicación en ejecución que se integra con
Application Insights. Puedes obtener información sobre cómo integrar la
aplicación con Application Insights en https://docs.microsoft.com/en-
us/azure/application-insights/app-insights-asp-net.

Se recomienda crear esta receta y las dos siguientes en una


aplicación de la función de Azure independiente basada en el
runtime v1, ya que estas plantillas no están disponibles en v2
todavía. Si en este momento no aparece la plantilla Análisis
programados de Application Insights, cambia la versión del
runtime de Azure Functions a v1. Para ello, establece el valor de
FUNCTIONS_EXTENSIONS_VERSION en ~1, como se muestra
en la siguiente captura de pantalla, en Configuración de la
aplicación de Azure Functions:

Cómo hacerlo...
Vamos a llevar a cabo los siguientes pasos para insertar detalles de telemetría
personalizados en Análisis de Application Insights.
[ 171 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

Crear una función de Application Insights


Sigue estos pasos:
1. Crea una plantilla de función nueva. Para ello, selecciona Supervisión en
la lista desplegable Escenario, como se muestra en la siguiente captura de
pantalla. También puedes buscar análisis programados para encontrar
fácilmente la plantilla:

2. Ahora, haz clic en C# (que aparece en la captura de pantalla anterior)


y proporciona el nombre y la frecuencia de programación a la que debe
ejecutarse la función:

3. Como se muestra en la captura de pantalla anterior, haz clic en el botón Crear


para crear la función.
[ 172 ]
Capítulo 6

Configurar claves de acceso


Sigue estos pasos:

1. Ve a la hoja Información general de Application Insights, tal como se


muestra, y copia la Clave de instrumentación. Vamos a utilizar la Clave
de instrumentación para crear una configuración de aplicación denominada
AI_IKEY en la aplicación de la función:

2. Ve a la hoja Acceso de API y copia el Id. de aplicación. Vamos a utilizar


este Id. de aplicación para crear una nueva configuración de aplicación
con el nombre AI_APP_ID en la aplicación de función:

3. También tenemos que crear una nueva clave de API. Como se muestra en
el paso anterior, haz clic en el botón Crear clave de API para generar la
nueva clave de API, como se muestra en la siguiente captura de pantalla.
Proporciona un nombre descriptivo, comprueba los datos de Leer telemetría
y haz clic en Generar clave:

[ 173 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

4. Poco después, podrás ver y copiar la clave, como se muestra en la siguiente


captura de pantalla. Vamos a utilizar esto para crear una nueva configuración
de aplicación con el nombre AI_APP_KEY en nuestra aplicación de función:

[ 174 ]
Capítulo 6

5. Crea las tres claves de configuración de aplicaciones en la aplicación


de función, como se muestra en la siguiente captura de pantalla. Estas
tres claves se utilizarán en nuestra función de Azure denominada
FeedAIwithCustomDerivedMetric.

Integrar y probar una consulta de Application


Insights
Sigue estos pasos:
1. Ahora, vamos a desarrollar una consulta que nos proporcione el valor de la
métrica derivada solicitudes por hora. Ve a la hoja Información general
de Application Insights y haz clic en el botón Análisis.
2. A continuación, se abrirá la hoja Análisis. Escribe la siguiente consulta en la
pestaña de consultas. Puedes escribir tu propia consulta según tus requisitos.
Asegúrate de que la consulta devuelve un valor escalar:
requests
| where timestamp > now(-1h)
| summarize count()

3. Una vez realizada la consulta, ejecútala haciendo clic en el botón Ejecutar


para ver el recuento de registros, como se muestra en la siguiente captura
de pantalla:

[ 175 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

4. Ahora ya tenemos lista la consulta de Application Insights


requerida. Vamos a integrar la consulta con nuestra función
FeedAIwithCustomDerivedMetrics. Ve al editor de código de Azure
Functions y realiza los siguientes cambios:
1. Proporciona un nombre descriptivo para la métrica derivada, en este
caso, Solicitudes por hora.
2. Reemplaza la consulta predeterminada con la que hemos
desarrollado.
3. Guarda los cambios a través del botón Guardar:

5. Vamos a llevar a cabo una prueba rápida para comprobar si has configurado
los tres ajustes de la aplicación y la consulta correctamente. Ve a la pestaña
Integrar y cambia la frecuencia de ejecución a un minuto, como se muestra
en la captura de pantalla siguiente:

[ 176 ]
Capítulo 6

6. Ahora, abriremos la pestaña Supervisar para ver si todo funciona


correctamente. Si hay algún problema, aparecerá una marca X en la columna
Estado. Consulta el error en la sección Registros de la pestaña Supervisar
haciendo clic en la entrada Registro de invocaciones:

7. Asegúrate de que la función se está ejecutando sin problemas e invierte la


frecuencia de programación a una hora.

Configurar el informe de métrica derivada


personalizada
Sigue estos pasos:

1. Ve a la pestaña Información general de Application Insights y haz clic en el


menú Métrica, como se muestra en la siguiente captura de pantalla:

2. En el Explorador de métricas podrás encontrar todos los análisis relativos


a las diferentes métricas. En el Explorador de métricas, haz clic en el botón
Editar de cualquier informe para configurar tu métrica personalizada, como
se muestra en la siguiente captura de pantalla (o puedes hacer clic en el botón
Agregar gráfico en la parte superior izquierda de la siguiente captura de
pantalla):

[ 177 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

3. A continuación, se abrirá la hoja Detalles de gráfico, donde puedes


configurar tu métrica personalizada y todos los detalles restantes
relacionados con el gráfico. En la lista desplegable ESPACIO DE NOMBRES
DE MÉTRICAS, selecciona azure.applicationinsghts, como se muestra en
la siguiente captura de pantalla, y luego selecciona la métrica personalizada
solicitudes por hora que hayas creado:

[ 178 ]
Capítulo 6

4. A continuación, se creará el gráfico, como se muestra en la siguiente captura


de pantalla:

Cómo funciona...
Así es como funciona todo el proceso:

• Hemos creado la función de Azure mediante la plantilla de Análisis


programados de Application Insights.
• Hemos configurado las siguientes claves en la Configuración de la
aplicación de Function App de Azure:
°° Clave de instrumentación de Application Insights
°° Id. de la aplicación
°° Clave de acceso de la API

• El runtime de la función de Azure ha consumido automáticamente la API de


Application Insights, ha ejecutado la consulta personalizada para recuperar
las métricas necesarias y ha realizado las operaciones necesarias para
proporcionar los datos de telemetría derivados a Application Insights.

[ 179 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

• Una vez configurados todos los parámetros de la función de Azure, hemos


desarrollado una consulta sencilla que nos ha permitido obtener el recuento
de la última hora y lo ha transferido a Application Insights como una métrica
derivada personalizada. Este proceso se repite cada hora.
• Posteriormente, hemos configurado un informe nuevo a través de las
métricas de Application Insights con nuestra métrica derivada personalizada.

Enviar datos de telemetría de la


aplicación por correo electrónico
Una de las actividades de tu aplicación, una vez activa, será recibir un correo
electrónico de notificación con información de estado, errores, tiempo de respuesta,
etc., al menos una vez al día.

Azure Functions nos permite obtener todos los datos básicos mediante una plantilla
de función con código que es responsable de recuperar todos los valores necesarios
de Application Insights y el código de asociación que enmarca el cuerpo del
correo electrónico y envía el correo electrónico mediante SendGrid. En esta receta,
aprenderemos cómo hacerlo.

Preparación
Sigue estos pasos de requisitos previos:

1. Crea una nueva cuenta de SendGrid, si no la has creado todavía, y obtén la


clave de la API de SendGrid.
2. Crea una cuenta de Application Insights nueva si aún no tienes una.
3. Asegúrate de que tienes una aplicación en ejecución que se integra con
Application Insights.

Puedes obtener información sobre cómo integrar la aplicación con


Application Insights en https://docs.microsoft.com/en-us/
azure/application-insights/app-insights-asp-net.

[ 180 ]
Capítulo 6

Cómo hacerlo...
Sigue estos pasos:

1. Para crear una nueva función, selecciona Supervisión en la lista desplegable


Escenario y selecciona la plantilla Resumen programado de Application
Insights: C#, como se muestra en la siguiente captura de pantalla:

2. Poco después, tendrás que proporciona el nombre de la función, la frecuencia


programada y la Clave de API de SendGrid para el enlace de salida de
SendGrid, como se muestra en la siguiente captura de pantalla:

[ 181 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

3. A continuación, haz clic en el botón Crear mostrado en el paso anterior para


crear la nueva función de Azure. La plantilla crea todo el código necesario
para consultar los datos de Application Insights y envía un correo electrónico
a la persona mencionada en el campo Dirección de destino de la captura de
pantalla anterior.

Asegúrate de seguir los pasos descritos en la sección Configurar claves de


acceso de la receta Insertar datos de telemetría personalizada en análisis
de Application Insights para configurar estas claves de acceso: Clave de
instrumentación de Application Insights, el Id. de la aplicación y la clave
de acceso de la API.

4. Ve a la función run.csx y cambia el nombre de la aplicación por el nombre


de tu aplicación, como se muestra en la siguiente captura de pantalla:

5. Si has configurado todos los ajustes correctamente, comenzarás a recibir


correos electrónicos basados en la configuración del temporizador.
6. Hagamos una ejecución de prueba rápida haciendo clic en el botón Ejecutar
situado encima del editor de código, como se muestra en la siguiente captura
de pantalla:

7. Esta es una captura de pantalla del correo electrónico que recibí después
de hacer clic en el botón Ejecutar en la captura de pantalla anterior:

[ 182 ]
Capítulo 6

Cómo funciona...
La función de Azure usa la API de Application Insights para ejecutar todas las
consultas de Análisis de Application Insights, recupera todos los resultados, enmarca
el cuerpo del correo electrónico con todos los datos e invoca la API de SendGrid para
que envíe un correo electrónico a la cuenta de correo electrónico configurada.

Y eso no es todo…
Las plantillas de Azure proporcionan un código predeterminado que contiene
una serie de consultas que suelen resultar útiles para supervisar el estado de las
aplicaciones. Si tienes requisitos específicos para obtener alertas de notificación,
continúa y agrega nuevas consultas al método GetQueryString. Para incorporar los
nuevos valores, también tendrás que cambiar la clase DigestResult y la función
GetHtmlContentValue.

Consulta también
La receta Enviar una notificación por correo electrónico al administrador del sitio web
mediante el servicio SendGrid del capítulo 2, Trabajar con notificaciones mediante los
servicios SendGrid y Twilio.

Integrar datos de supervisión de


Application Insights en tiempo real con
Power BI mediante Azure Functions
En ocasiones, necesitarás ver datos en tiempo real sobre la disponibilidad de
tu aplicación o información relacionada con el estado de esta en un sitio web
personalizado. Recuperar información de Application Insights e integrarla en un
informe personalizado es un trabajo tedioso, ya que habría que desarrollar un sitio
web independiente y, luego, crearlo, probarlo y alojarlo en algún sitio.

En esta receta, comprobarás lo fácil que es ver información de estado de la aplicación


en tiempo real mediante la integración de Application Insights y Power BI. Para ello,
vamos a aprovechar las capacidades de Power BI para la transmisión en directo de
datos y las funciones de temporizador de Azure para proporcionar la información de
estado a Power BI de manera continua. A continuación, se muestra un diagrama de
alto nivel de lo que vamos a hacer en la última parte de esta receta:

[ 183 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

En esta receta, vamos a utilizar la plantilla de Power BI de Application


Insights de una aplicación de función creada con el runtime de
Azure Functions v1. El runtime de Azure Functions V2 no cuenta con
ella. Si estás utilizando el runtime v2, puedes crear simplemente un
desencadenador de temporizador y seguir las instrucciones de esta
receta.

Preparación
Sigue estos pasos de requisitos previos:

1. Crea una cuenta de Power BI en https://powerbi.microsoft.com/.


2. Crea una cuenta de Application Insights nueva si aún no tienes una.
3. Asegúrate de que tienes una aplicación en ejecución que se integra con
Application Insights. Puedes obtener información sobre cómo integrar la
aplicación con Application Insights en https://docs.microsoft.com/en-
us/azure/application-insights/app-insights-asp-net.

[ 184 ]
Capítulo 6

Debes utilizar tu cuenta de profesional para crear una cuenta de Power BI.
En el momento de redactar esta receta, no fue posible crear una cuenta de
Power BI con una dirección de correo electrónico personal, por ejemplo,
de Gmail, Yahoo, etc.
Asegúrate de seguir los pasos descritos en la sección Configurar claves de
acceso de la receta Insertar datos de telemetría personalizada en análisis
de Application Insights para configurar estas claves de acceso: Clave de
instrumentación de Application Insights, el Id. de la aplicación y la clave
de acceso de la API.

Cómo hacerlo...
Vamos a seguir estos pasos para integrar Application Insights y Power BI.

Configurar Power BI con un panel, un conjunto de


datos y el URI de inserción
Sigue estos pasos:
1. Si estás utilizando el portal de Power BI por primera vez, es posible que
tengas que hacer clic en Omitir en la página de bienvenida, como se muestra
en la siguiente captura de pantalla:

[ 185 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

2. El siguiente paso es crear un conjunto de datos de transmisión. Para ello, haz


clic en Crear y, a continuación, selecciona Conjunto de datos de transmisión,
como se muestra en la siguiente captura de pantalla:

3. En el paso Nuevo conjunto de datos de transmisión, selecciona API


y haz clic en el botón Siguiente, como se muestra en la siguiente captura
de pantalla:

[ 186 ]
Capítulo 6

4. En el paso siguiente, debes crear los campos para el conjunto de datos de


transmisión. Proporciona un nombre descriptivo para el conjunto de datos
y proporciona los valores que te gustaría enviar a Power BI. Para esta
receta, he creado un conjunto de datos con un solo campo, denominado
RequestsPerSecond, de tipo Número y he hecho clic en Crear, como se
muestra en la siguiente captura de pantalla:

5. Una vez creado el conjunto de datos, se te pedirá que proporciones una


URL de inserción, como se muestra en la siguiente captura de pantalla.
Utilizarás esta URL de inserción en Azure Functions para insertar los datos
RequestsPerSecond cada segundo (o según tus requisitos) con el valor real
de las solicitudes por segundo. Haz clic en Hecho:

[ 187 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

6. El siguiente paso es crear un panel con un icono en él. Vamos a crear un


nuevo panel. Para ello, haz clic en Crear y selecciona Panel, como se muestra
en la siguiente captura de pantalla:

[ 188 ]
Capítulo 6

7. En la ventana emergente Crear panel, proporciona un nombre descriptivo


y haz clic en Crear, como se muestra en la siguiente captura de pantalla, para
crear un panel vacío:

8. En el panel vacío, haz clic en el botón Agregar icono para crear un nuevo
icono. Al hacer clic en Agregar icono, se abrirá una ventana nueva donde
puedes seleccionar la fuente de datos de la que debe rellenarse el icono:

[ 189 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

9. Selecciona Datos de transmisión personalizados y haz clic en Siguiente,


como se muestra en la captura de pantalla anterior. En el siguiente paso,
selecciona el conjunto de datos Solicitudes y haz clic en el botón Siguiente:

10. El siguiente paso es elegir el Tipo de visualización (en este caso es Tarjeta)
y seleccionar los campos de la fuente de datos, como se muestra en la
siguiente captura de pantalla:

11. El último paso es proporcionar un nombre para el icono. Yo le he asignado


el nombre RequestsPerSecond. El nombre no tiene por qué tener sentido en
este caso; puedes ponerle el que desees en función de tus requisitos.
[ 190 ]
Capítulo 6

Crear una función C# de Power BI en tiempo real


para Azure Application Insights
Para crear una función C# de Power BI en tiempo real para Azure Application
Insights, sigue estos pasos:

1. Ve a Azure Functions y crea una nueva función con la siguiente plantilla:

2. Haz clic en C# en la captura de pantalla anterior, proporciona el Nombre


y haz clic en el botón Crear, como se muestra en la siguiente captura
de pantalla:

[ 191 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

3. Reemplaza el código predeterminado por el código siguiente. Asegúrate de


configurar el valor correcto para el que la consulta de análisis debe extraer los
datos. En mi caso, he especificado cinco minutos (5 m) en el siguiente código:
#r "Newtonsoft.Json"
using System.Configuration;
using System.Text;
using Newtonsoft.Json.Linq;
private const string AppInsightsApi =
"https://api.applicationinsights.io/beta/apps";
private const string RealTimePushURL =
"PastethePushURLhere";
private static readonly string AiAppId =
ConfigurationManager.AppSettings["AI_APP_ID"];
private static readonly string AiAppKey =
ConfigurationManager.AppSettings["AI_APP_KEY"];

public static async Task Run(TimerInfo myTimer,


TraceWriter
log)
{
if (myTimer.IsPastDue)
{
log.Warning($"[Warning]: Timer is running late! Last
ran
at: {myTimer.ScheduleStatus.Last}");
}
await RealTimeFeedRun(
query: @"
requests
| where timestamp > ago(5m)
| summarize passed = countif(success == true),
total = count()
| project passed
",
log: log
);
log.Info($"Executing real-time Power BI run at:
{DateTime.Now}");
}

private static async Task RealTimeFeedRun( string query,


TraceWriter log)
{
log.Info($"Feeding Data to Power BI has started at:
{DateTime.Now}");
string requestId = Guid.NewGuid().ToString();
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("x-api-key",

[ 192 ]
Capítulo 6

AiAppKey);
httpClient.DefaultRequestHeaders.Add("x-ms-app",
"FunctionTemplate");
httpClient.DefaultRequestHeaders.Add("x-ms-client-
request-id", requestId);
string apiPath = $"{AppInsightsApi}/{AiAppId}/query?
clientId={requestId}&timespan=P1D&query={query}";
using (var httpResponse = await
httpClient.GetAsync(apiPath))
{
httpResponse.EnsureSuccessStatusCode();
var resultJson = await
httpResponse.Content.ReadAsAsync<JToken>();
double result;
if (!double.TryParse(resultJson.SelectToken
("Tables[0].Rows[0][0]")?.ToString(), out
result))
{
throw new FormatException("Query must result
in a
single metric number. Try it on Analytics
before
scheduling.");
}
string postData = $"[{{ "requests": "{result}"
}}]";
log.Verbose($"[Verbose]: Sending data:
{postData}");
using (var response = await
httpClient.PostAsync(RealTimePushURL, new
ByteArrayContent(Encoding.UTF8.
GetBytes(postData))))
{
log.Verbose($"[Verbose]: Data sent with
response:
{response.StatusCode}");
}
}
}
}

El código anterior ejecuta una consulta de análisis de Application Insights


que extrae datos de los últimos cinco minutos (solicitudes) y envía los
datos a la dirección URL de inserción de Power BI. Este proceso se repite
continuamente conforme a la frecuencia de temporizador configurada.

[ 193 ]
Supervisar y solucionar problemas de los servicios de Azure sin servidor

4. En la captura de pantalla siguiente se muestra una secuencia de imágenes


que contienen los datos en tiempo real:

Cómo funciona...
Hemos creado lo siguiente en este orden específico:

1. Un conjunto de datos de transmisión en la aplicación de Power BI


2. Un panel y un nuevo icono que pueden mostrar los valores disponibles en el
conjunto de datos de transmisión
3. Una nueva función de Azure que ejecuta una consulta de Análisis de
Application Insights y proporciona los datos a Power BI a través de la URL
de inserción del conjunto de datos
4. Una vez hecho todo, se podrán ver los datos en tiempo real del icono de
Power BI del panel

Y eso no es todo…
• Power BI nos permite crear datos en tiempo real en informes de varias
maneras. En esta receta, has aprendido a crear informes en tiempo real
mediante el conjunto de datos de transmisión. Las otras formas de crearlos
son con el conjunto de datos de inserción y con el conjunto de datos de
transmisión de PubNub. Puedes obtener más información sobre los tres
procedimientos en https://powerbi.microsoft.com/documentation/
powerbi-service-real-time-streaming/.
• Debes prestar especial cuidado cuando intentes obtener datos de estado de
la aplicación en tiempo real. La API de Application Insights tiene un límite
de velocidad. Echa un vistazo a https://dev.applicationinsights.
io/documentation/Authorization/Rate-limits para obtener más
información acerca de los límites de API.

[ 194 ]
Desarrollar aplicaciones
fiables sin servidor mediante
Durable Functions
En este capítulo, vas a aprender lo siguiente:

• Configurar Durable Functions en el portal de administración de Azure


• Crear una aplicación Hola, mundo de Durable Functions
• Probar y solucionar problemas de Durable Functions
• Implementar aplicaciones fiables multiproceso mediante Durable Functions

Introducción
Al trabajar en el desarrollo de aplicaciones modernas que deban estar alojadas en
el cloud, debes asegurarte de que las aplicaciones no tengan estado. El hecho de no
tener estado es un factor esencial para el desarrollo de aplicaciones compatibles con
el cloud. Por ejemplo, debes evitar la persistencia de cualquier dato en el recurso que
sea específico para cualquier instancia de máquina virtual (VM) aprovisionada para
cualquier servicio de Azure (por ejemplo, el servicio de aplicaciones, la API, etc.).
Si lo haces, no puedes aprovechar algunos de los servicios, como la funcionalidad
de escalado automático, ya que el aprovisionamiento de instancias es dinámico.
Si dependes de algún recurso específico de la máquina virtual, te encontrarás con
comportamientos inesperados.

Dicho esto, la desventaja del enfoque mencionado anteriormente es que terminas


trabajando en la identificación de formas de persistencia de datos en diferentes
medios, dependiendo de la arquitectura de tu aplicación.

[ 196 ]
Capítulo 7

Para obtener más información sobre Durable Functions, consulta la


documentación oficial, disponible en https://docs.microsoft.com/
en-us/azure/azure-functions/durable-functions-overview.

Configurar Durable Functions en el portal


de administración de Azure
Azure ha ideado una nueva forma de manejar el hecho de no tener estado en la
arquitectura sin servidor, junto con otras características, como la durabilidad y la
fiabilidad, en forma de Durable Functions. Está disponible como una extensión de
Azure Functions. En este capítulo, comenzaremos a descubrir las Durable Functions.

Preparación
Crea una nueva aplicación de función si aún no está creada. Asegúrate de que la
versión del runtime sea ~2 en Configuración de la aplicación, como se muestra
en la siguiente captura de pantalla:

[ 197 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

Cómo hacerlo...
Sigue estos pasos:

1. Haz clic en el botón + para crear una función nueva:

2. Crea una nueva función de inicio HTTP de Durable Functions


seleccionando Durable Functions en el menú desplegable Escenario,
como se muestra en la siguiente captura de pantalla:

3. Posteriormente, se abrirá una pestaña nueva:

[ 198 ]
Capítulo 7

4. Haz clic en el botón Instalar, que se muestra en el paso anterior, para


iniciar la instalación de extensiones DurableTask. La instalación de las
dependencias debería de llevar alrededor de dos minutos:

5. Una vez que se complete el proceso, debe aparecer lo siguiente:

Y eso no es todo…
Actualmente, C# es el único lenguaje compatible para el desarrollo de Durable
Functions. La compatibilidad con otros lenguajes se encuentra en la fase de preview.

[ 199 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

Crear una aplicación Hola, mundo


de Durable Functions
Aunque la intención general de este libro es que cada receta de cada capítulo
resuelva al menos un problema empresarial, esta receta no resuelve ningún
problema de dominio en tiempo real. En su lugar, proporciona orientación de inicio
rápido para ayudarte a comprender mejor las Durable Functions y sus componentes,
junto con el enfoque del desarrollo de Durable Functions. En el siguiente capítulo,
descubriremos lo fácil que es desarrollar una aplicación basada en el flujo de trabajo
utilizando Durable Functions.

Preparación
Antes de seguir avanzando, vamos a seguir estos pasos:

1. Si no lo has hecho ya, descarga e instala Postman desde


https://www.getpostman.com/
2. Obtén más información acerca del orquestador y los enlaces de
desencadenador de actividad en https://docs.microsoft.com/en-us/
azure/azure-functions/durable-functions-bindings

Cómo hacerlo...
Para desarrollar Durable Functions, es necesario que creemos las tres funciones
siguientes:

• Cliente de orquestador: una función de Azure que puede administrar


instancias de orquestador.
• Función de orquestador: la función real de orquestador permite el desarrollo
de flujos de trabajo con estado a través de código. Estas funciones pueden
llamar de forma asincrónica a otras Azure Functions (denominadas
Funciones de actividad), e incluso pueden guardar los valores devueltos de
estas funciones en variables locales.
• Funciones de actividad: son las funciones a las que llamarán las funciones
del orquestador.

[ 200 ]
Capítulo 7

Crear una función HttpStart en el cliente


de orquestador
Sigue estos pasos:

1. Crea una nueva función de inicio HTTP de Durable Functions seleccionando


Durable Functions en el menú desplegable Escenario y haz clic en el inicio
HTTP de Durable Functions, que abre una pestaña nueva que se muestra
a continuación. Vamos a crear una nueva función HTTP denominada
HttpStart:

2. Poco después, se te dirigirá al editor de código. La siguiente función es un


desencadenador de HTTP que acepta el nombre de la función que debe
ejecutarse junto con la entrada. Utiliza el método StartNewAsync del objeto
DurableOrchestrationClient para iniciar la orquestación:
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
#r "Newtonsoft.Json"

using System.Net;

public static async Task<HttpResponseMessage> Run(


HttpRequestMessage req,
DurableOrchestrationClient starter,
string functionName,
ILogger log)
{
// Function input comes from the request content.
dynamic eventData = await req.Content.
ReadAsAsync<object>();
string instanceId = await starter.
StartNewAsync(functionName,
[ 201 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

eventData);

log.LogInformation($"Started orchestration with ID =


'{instanceId}'.");

return starter.CreateCheckStatusResponse(req,
instanceId);
}

3. Ve a la pestaña Integrar y haz clic en Editor avanzado, como se muestra


en la siguiente captura de pantalla:

4. En el Editor avanzado, los enlaces deben ser similares a los siguientes. En


caso contrario, reemplaza el código predeterminado por el código siguiente:
{
"bindings":
[
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": [
"post",
"get"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",

[ 202 ]
Capítulo 7

"type": "orchestrationClient",
"direction": "in"
}
]
}

La función HttpStart actúa como una puerta de enlace


para invocar todas las funciones de la aplicación de función.
Cualquier solicitud que realices utilizando el formato de URL
https://<durablefunctionname>>.azurewebsites.net/
api/orchestrators/{functionName} la recibirá esta función
HttpStart. Esta función se encargará de ejecutar la función de
orquestador en función del parámetro disponible en el parámetro
de ruta {functionName}. Todo esto es posible con el atributo de ruta,
definido en function.json de la función HttpStart.

Crear la función de orquestador


Sigue estos pasos:

1. Vamos a crear una función de orquestador haciendo clic en la plantilla


Orquestador de Durable Functions, como se muestra a continuación:

2. Después de hacer clic en el mosaico Orquestador de Durable Functions, se


te redirigirá a la pestaña siguiente donde proporcionarás el nombre de la
función. Después de proporcionar el nombre, haz clic en el botón Crear
para crear la función de orquestador:

[ 203 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

3. En DurableFuncManager, reemplaza el código predeterminado con el


siguiente y haz clic en el botón Guardar para guardar los cambios: el
siguiente orquestador llamará a las funciones de actividad mediante el
método CallActivityAsync del objeto DurableOrchestraionContext:
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
public static async Task<List<string>>
Run(DurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>
("ConveyGreeting", "Welcome Cookbook Readers"));
return outputs;
}

4. En el Editor avanzado de la pestaña Integrar, sustituye el código


predeterminado por el código siguiente:
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}

[ 204 ]
Capítulo 7

Crear una función de actividad


Sigue estos pasos:

1. Crea una función nueva denominada ConveyGreeting utilizando la plantilla


Actividad de Durable Functions:

2. Sustituye el código predeterminado por el código siguiente que solo muestra


el nombre que se proporciona como entrada y, a continuación, haz clic en el
botón Guardar para guardar los cambios:
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
public static string Run(string name)
{
return $"Hello Welcome Cookbook Readers!";
}

3. En el Editor avanzado de la pestaña Integrar, sustituye el código


predeterminado por el código siguiente:
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
]
}

En esta receta, hemos creado un cliente de orquestación, una función de orquestador


y una función de actividad. Descubriremos cómo probarlos en nuestra próxima
receta.

[ 205 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

Cómo funciona...
Echemos un vistazo al funcionamiento de la receta:

• Primero desarrollamos el cliente de orquestador (en nuestro caso,


HttpStart), que es capaz de crear orquestadores utilizando la función
StartNewAsync de la clase DurableOrchestrationClient. Este método
crea una nueva instancia de orquestador.
• Después, desarrollamos la función de orquestador, la parte más importante
de Durable Functions. A continuación, encontramos algunas de las
características principales más importantes del contexto de orquestador:
° Puede invocar varias funciones de actividad
° Puede guardar la salida devuelta por una función de actividad y
pasarla a otra función de actividad.
° Estas funciones de orquestador también son capaces de crear puntos
de control que guardan puntos de ejecución, de modo que si hay
algún problema con las máquinas virtuales, es posible reemplazar
o reanudar el servicio automáticamente.

• Y, por último, desarrollamos la función de actividad, donde escribimos la


mayor parte de la lógica empresarial. En nuestro caso, solo está devolviendo
un mensaje simple.

Y eso no es todo…
Las Durable Functions dependen del marco de tareas durables. Puedes obtener más
información sobre el marco de tareas durables en https://github.com/Azure/
durabletask.

Probar y solucionar problemas de


Durable Functions
En los capítulos anteriores, hemos analizado varias formas de probar Azure
Functions. Podemos probar Durable Functions con el mismo conjunto de
herramientas. Sin embargo, el enfoque de las pruebas es completamente diferente
debido a sus características y la forma en que funciona.

En esta receta, descubriremos algunas de las cosas esenciales que uno debe tener
en cuenta al trabajar con Durable Functions.

[ 206 ]
Capítulo 7

Preparación
Si aún no lo has hecho, descarga e instala:

• La herramienta Postman, disponible en https://www.getpostman.com.


• Explorador de Microsoft Azure Storage, disponible en http://
storageexplorer.com.

Cómo hacerlo...
Sigue estos pasos:

1. Desplázate hasta el editor de código de la función HttpStart y obtén la URL


haciendo clic en </>Obtener la dirección URL de la función. Sustituye el
valor de la plantilla {functionName} por DurableFuncManager.
2. Hagamos una solicitud POST mediante Postman:

3. Después de hacer clic en el botón Guardar, obtendrás una respuesta con lo


siguiente:
° El ID de instancia
° La dirección URL para recuperar el estado de la función
° La dirección URL para enviar un evento a la función
° La dirección URL para finalizar la solicitud

4. Haz clic en statusQueryGetUri en el paso anterior para ver el estado de la


función. Al hacer clic en el enlace en el paso anterior, se abrirá la consulta en
una pestaña nueva de la herramienta Postman. Una vez abierta la pestaña
nueva, haz clic en el botón Enviar para obtener el resultado real:

[ 207 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

5. Si todo va bien, podemos ver runtimeStatus como Completado en Postman,


como se muestra en la captura de pantalla anterior. También obtendrás ocho
registros en el almacenamiento de tablas, donde se almacena el historial de
ejecución, que se muestra a continuación:

6. Si algo ha ido mal, puedes ver el mensaje de error en la columna de


resultados, en la que se detalla en qué función ha ocurrido el error.
A continuación, desplázate a la pestaña Monitor de esa función para
ver una explicación detallada del error.

[ 208 ]
Capítulo 7

Implementar aplicaciones fiables


multiproceso mediante Durable Functions
He trabajado en algunas de las aplicaciones donde se requiere la ejecución paralela
para realizar algunas tareas informáticas. La ventaja principal de este enfoque es
que se obtiene el resultado deseado con bastante rapidez según los subprocesos que
se creen. Se podría lograr de varias maneras utilizando diferentes tecnologías. Sin
embargo, el desafío en estos enfoques es que, si algo sale mal en medio de cualquiera
de los subprocesos, no es fácil realizar la autorreparación y reanudar desde el punto
en el que se detuvo. Estoy seguro de que muchos de vosotros os habéis enfrentado
a problemas similares en vuestra aplicación, ya que es un caso empresarial muy
común.

En esta receta, implementaremos una forma sencilla de ejecutar una función en


paralelo con varias instancias utilizando Durable Functions para el siguiente
escenario.

Supongamos que tenemos cinco clientes (cuyos ID son 1, 2, 3, 4 y 5, respectivamente)


que se nos acercaron para generar una gran cantidad de códigos de barras (por
ejemplo, alrededor de 50 000). Tomaría mucho tiempo generar los códigos de barras,
ya que implicaría algunas tareas de procesamiento de imágenes. Por lo tanto, una
forma sencilla de procesar rápidamente la solicitud es utilizar la programación
asincrónica creando un hilo para cada uno de los clientes y luego ejecutando la
lógica en paralelo para cada uno de ellos.

También simularemos un caso de uso simple para comprender cómo las Durable
Functions se reparan automáticamente cuando la máquina virtual en la que están
alojadas se desactiva o se reinicia.

Preparación
Si aún no lo has hecho, instala:

• La herramienta Postman, disponible en https://www.getpostman.com/


• Explorador de Microsoft Azure Storage, disponible en http://
storageexplorer.com/

[ 209 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

Cómo hacerlo...
En esta receta, crearemos los siguientes desencadenadores de la función de Azure:
• Una función de orquestador, denominada GenerateBARCode
• Dos funciones de desencadenador de actividad, que son:
° GetAllCustomers: para hacerlo simple, esta función simplemente
devuelve la matriz de ID de clientes. En tus aplicaciones del mundo real,
dispondrías de lógica empresarial que decidiría qué clientes son aptos y,
en función de esa lógica, devolverías los ID de los clientes aptos.
° CreateBARCodeImagesPerCustomer: esta función no crea realmente
el código de barras; más bien, simplemente registra un mensaje en la
consola, ya que nuestro objetivo es comprender las características de
las Durable Functions. Para cada cliente, generaremos aleatoriamente
un número inferior a 50 000 y simplemente iteraremos a través de ese
número.

Crear la función de orquestador


Sigue estos pasos:

1. Crea una función nueva denominada GenerateBARCode utilizando


la plantilla orquestador de Durable Functions. Reemplaza el código
predeterminado por el siguiente y haz clic en el botón Guardar para guardar
los cambios. El siguiente código clasifica inicialmente la función de actividad
GetAllCustomers, almacena todos los identificadores de los clientes en una
matriz y luego, para cada cliente, vuelve a llamar a otra función de actividad
que devuelve el número de códigos de barras que se generan. Finalmente,
espera hasta que las funciones de actividad para todos los clientes se
completen y luego devuelve la suma de todos los códigos de barras que
se generan para todos los clientes.
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
public static async Task<int> Run(
DurableOrchestrationContext context)
{
int[] customers = await
context.CallActivityAsync<int[]>("GetAllCustomers",null);

var tasks = new Task<int>[customers.Length];


for (int nCustomerIndex = 0; nCustomerIndex < customers.
Length; nCustomerIndex++)
{
tasks[nCustomerIndex] = context.CallActivityAsync<int>
("CreateBARCodeImagesPerCustomer",
customers[nCustomerIndex]);
[ 210 ]
Capítulo 7

await Task.WhenAll(tasks);
int nTotalItems = tasks.Sum(item => item.Result);

return nTotalItems;
}

2. En el Editor avanzado de la pestaña Integrar, sustituye el código


predeterminado por el código siguiente:
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}

Crear una función de actividad GetAllCustomers


Sigue estos pasos:

1. Crea una función nueva denominada GetAllCustomers con la plantilla de


actividad de Durable Functions, sustituye el código predeterminado por el
código siguiente y, a continuación, haz clic en el botón Guardar para guardar
los cambios:
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
public static int[] Run(string name)
{
int[] customers = new int[]{1,2,3,4,5};
return customers;
}

2. En el Editor avanzado de la pestaña Integrar, sustituye el código


predeterminado por el código siguiente:
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",

[ 211 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

"direction": "in"
}
]
}

Crear una función de actividad


CreateBARCodeImagesPerCustomer
Sigue estos pasos:

1. Crea una función nueva denominada CreateBARCodeImagesPerCustomer


utilizando la plantilla Actividad de Durable Functions. Reemplaza el código
predeterminado por el siguiente y luego haz clic en el botón Guardar para
guardar los cambios:
#r "Microsoft.Azure.WebJobs.Extensions.DurableTask"
#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage.Blob;

public static async Task<int> Run(DurableActivityContext


customerContext,ILogger log)
{
int ncustomerId = Convert.ToInt32
(customerContext.GetInput<string>());
Random objRandom = new Random(Guid.NewGuid().
GetHashCode());
int nRandomValue = objRandom.Next(50000);
for(int nProcessIndex = 0;nProcessIndex<=nRandomValue;
nProcessIndex++)
{
log.LogInformation($" running for {nProcessIndex}");
}
return nRandomValue;
}

2. En el Editor avanzado de la pestaña Integrar, sustituye el código


predeterminado por el código siguiente:
{
"bindings": [
{
"name": "customerContext",
"type": "activityTrigger",
"direction": "in"
}
]
}
[ 212 ]
Capítulo 7

3. Vamos a ejecutar la función con Postman. Detendremos App Service para


simular un reinicio de la máquina virtual en la que se ejecutaría la función
para ver cómo Durable Function reanuda el proceso desde el punto en el
que se detuvo.
4. Realiza una solicitud POST utilizando Postman, como se muestra
a continuación:

5. Después de hacer clic en el botón Guardar, obtendrás una respuesta con la


dirección URL de estado. Haz clic en statusQueryGetURi para ver el estado
de la función. Al hacer clic en el enlace statusQueryGetURi, se abrirá en una
pestaña nueva en la herramienta Postman. Una vez abierta la pestaña nueva,
haz clic en el botón Enviar para ver el progreso de la función.
6. Mientras se está ejecutando la función, dirígete a la hoja Información
general de la aplicación de función y detén el servicio haciendo clic en
el botón Detener:

7. La ejecución de la función se detendrá a la mitad. Vayamos a nuestra


cuenta de almacenamiento en Storage Explorer y abramos la tabla
DurableFunctionsHubHistory para ver el progreso:

8. Después de un tiempo (en mi caso, después de solo cinco minutos), vuelve


a la hoja Información general e inicia el servicio de aplicaciones de la
función. Verás que la Durable Function se reanudará desde el punto en el
que se detuvo. No escribimos ningún código para ello; es una característica
"out-of-the-box". A continuación, se muestra la captura de pantalla de la
función completada:
[ 213 ]
Desarrollar aplicaciones fiables sin servidor mediante Durable Functions

Cómo funciona...
Durable Functions nos permiten desarrollar una ejecución fiable de nuestras
funciones, lo que significa que, aunque las máquinas virtuales se bloqueen o se
reinicien mientras la función se esté ejecutando, vuelve automáticamente a su estado
anterior. Lo hace con la ayuda de lo que se denomina crear punto de comprobación
y reproducir, donde el historial de la ejecución se almacena en la tabla de
almacenamiento.

Puedes ver más información sobre esta característica en https://


docs.microsoft.com/en-us/azure/azure-functions/
durable-functions-checkpointing-and-replay.

Y eso no es todo...
• Si obtienes la respuesta 404 No encontrado al ejecutar la dirección URL
statusQueryGetURi, no te preocupes. Llevará algún tiempo, pero finalmente
funcionará cuando hagas una solicitud más adelante.
• Para ver el historial de ejecución de tus Durable Functions, dirígete a la
tabla DurableFunctionsHubHistory, que se encuentra en la cuenta de
almacenamiento surgida al crear la aplicación de la función:

Encontrarás el nombre de la cuenta de almacenamiento en Configuración de la


aplicación, como se muestra en la captura de pantalla anterior.

[ 214 ]
Importación masiva de datos
mediante Cosmos DB
y Durable Functions de Azure
En este capítulo, abordaremos las siguientes recetas:

• Cargar datos de empleados en Blob Storage


• Crear un desencadenador de blob
• Crear el orquestador durable y activarlo para cada importación de Excel
• Leer datos de Excel mediante funciones de actividad
• Escalar automáticamente el rendimiento de Cosmos DB
• Insertar masivamente datos en Cosmos DB

Introducción
En este capítulo, vamos a desarrollar un miniproyecto con un caso de uso muy
común que resuelve el problema empresarial de compartir datos entre distintas
aplicaciones mediante Excel. Utilizaremos Durable Functions, una extensión de
Azure Functions que permite crear flujos de trabajo mediante la escritura de una
cantidad mínima de líneas de código.

[ 216 ]
Capítulo 8

A continuación, se indican las dos características principales de Durable Functions


que utilizaremos en las recetas de este capítulo:

• Orquestador: es la función responsable de gestionar todos los


desencadenadores de actividad. Se puede tratar como un administrador
de flujos de trabajo con varios pasos. El orquestador se encarga de
iniciar el desencadenador de actividad, pasar información de entrada al
desencadenador de actividad, obtener la información de salida, mantener el
estado y pasar la información de salida de un desencadenador de actividad
a otro si es necesario.
• Desencadenador de actividad: cada desencadenador de actividad se puede
considerar un paso del flujo de trabajo que realiza una función.

Puedes obtener más información sobre Durable Functions en https://


docs.microsoft.com/en-us/azure/azure-functions/
durable-functions-overview.

Problema empresarial
En general, las organizaciones utilizan distintas aplicaciones hospedadas en
múltiples plataformas de diferentes centros de datos (en el cloud u on-premises).
A menudo, es necesario que los datos de una aplicación se envíen a otro sistema.
Normalmente, las hojas de cálculo de Excel (y en algunos casos, los archivos JSON
o XML) se utilizan para exportar datos desde una aplicación e importarlos en otra.

La exportación de un archivo de Excel de una aplicación a otra puede parecer


sencilla. No obstante, cuando varias aplicaciones deben enviar datos a otras
aplicaciones de forma semanal o mensual, el trabajo se complica y hay muchas
posibilidades de que se produzcan errores manuales. Por lo tanto, la solución obvia
es automatizar el proceso en la medida de lo posible.

En este capítulo, aprenderemos a desarrollar una solución duradera basada


en una arquitectura sin servidor mediante Durable Functions. Si ya has leído
el capítulo 7, Desarrollo de aplicaciones fiables sin servidor mediante Durable Functions,
tendrás un conocimiento básico de qué son las Durable Functions y cómo funcionan.
En el capítulo 7, Desarrollo de aplicaciones fiables sin servidor mediante Durable Functions,
hemos implementado la solución desde el portal. Sin embargo, en este capítulo,
vamos a implementar un miniproyecto con Visual Studio 2017 (preferiblemente 15.5
o superior).

Antes de empezar a desarrollar el proyecto, debemos comprender la nueva forma de


implementar la solución sin servidor.

[ 217 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

Una forma duradera y sin servidor de


implementar una importación de Excel
En este diagrama se muestran todos los pasos necesarios para crear la solución
mediante la arquitectura sin servidor:

1. Las aplicaciones o clientes externos cargan un archivo de Excel en Blob


Storage.
2. El desencadenador de blob se activa cuando el archivo de Excel se carga
correctamente.
3. El orquestador durable se inicia desde el desencadenador de blob.
4. El orquestador invoca Leer Excel: desencadenador de actividad para leer
el contenido de Excel de Blob Storage.
5. El orquestador invoca Escalar RU: desencadenador de actividad para
ampliar el rendimiento de la colección de Cosmos DB para que se adapte
a la carga.
6. El orquestador invoca Importar datos: desencadenador de actividad para
preparar la colección para la importación masiva de datos.
7. Por último, Importar datos: desencadenador de actividad carga los datos de
la colección en la colección de Cosmos DB mediante los enlaces de salida de
Cosmos DB

Cargar datos de empleados en Blob


Storage
En esta receta, vamos a desarrollar una aplicación de consola para cargar la hoja de
Excel en Blob Storage.
[ 218 ]
Capítulo 8

Preparación
Establece los siguientes requisitos previos:

1. Instala Visual Studio 2017 (versión 15.5 o posterior).


2. Crea una cuenta de almacenamiento y un contenedor de blobs denominado
Excelimports.
3. Crea un archivo de Excel con datos de los empleados, tal como se muestra en
la siguiente captura de pantalla:

Cómo hacerlo...
Sigue estos pasos:

1. Crea una nueva aplicación de consola denominada ExcelImport.Client


mediante Visual Studio, tal como se muestra en la siguiente captura de
pantalla:

[ 219 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

2. Cuando el proyecto se haya creado, ejecuta los siguientes comandos en el


administrador de paquetes NuGet:
Install-Package Microsoft.Azure.Storage.Blob

Install-Package Microsoft.Extensions.Configuration

Install-Package Microsoft.Extensions.Configuration.FileExtensions

Install-Package Microsoft.Extensions.Configuration.Json
3. Añade los siguientes espacios de nombres en la parte superior del archivo
Program.cs:

using Microsoft.Extensions.Configuration;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.IO;
using System.Threading.Tasks;
4. El siguiente paso es desarrollar el código en una función denominada
UploadBlob que carga el archivo de Excel en el contenedor de blobs que
hemos creado. Para simplificar la tarea, el siguiente código cargará el archivo
de Excel desde una ubicación codificada de forma rígida. Sin embargo, en
una aplicación típica en tiempo real, este archivo lo cargaría el usuario final
mediante una interfaz web. Copia el siguiente código y pégalo en el archivo
Program.cs de la aplicación ExcelImport.Client:
private static async Task UploadBlob()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(“appsettings.json”, optional: true, reloadOnChange:
true);
IConfigurationRoot configuration = builder.Build();
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.
Parse(configuration.GetConnectionString(“StorageConnection”));
CloudBlobClient cloudBlobClient = cloudStorageAccount.
CreateCloudBlobClient();
CloudBlobContainer ExcelBlobContainer = cloudBlobClient.GetContain
erReference(“Excelimports”);
await ExcelBlobContainer.CreateIfNotExistsAsync();
CloudBlockBlob cloudBlockBlob = ExcelBlobContainer.GetBlockBlobRef
erence(“EmployeeInformation” + Guid.NewGuid().ToString());
await cloudBlockBlob.UploadFromFileAsync(@”C:\Users\
vmadmin\source\repos\POC\ImportExcelPOC\ImportExcelPOC\
EmployeeInformation.xlsx”);
}

[ 220 ]
Capítulo 8

5. Ahora, copia el siguiente código en la función Principal. Este fragmento de


código invoca la función UploadBlob, que es responsable de cargar el blob
a nivel interno:
{
UploadBlob().Wait();
}
catch (Exception ex)
{
Console.WriteLine(“An Error has occurred with the message” +
ex.Message);
}

6. El siguiente paso es crear un archivo de configuración denominado


appsettings.json, que contiene la cadena de conexión de la cuenta de
almacenamiento, tal como se muestra en la siguiente captura de pantalla:

7. Abre las propiedades del archivo appsettings.json y cambia la opción


Copiar en el directorio de salida por Copiar si es posterior para que el
programa pueda leer las propiedades tal como se muestra en la siguiente
captura de pantalla:

[ 221 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

8. Compila la aplicación e iníciala. Si has configurado todo, deberías ver algo


parecido a lo que se muestra en la siguiente captura de pantalla:

9. Vayamos a la cuenta de almacenamiento y al contenedor de blobs


denominado Excelimports, donde verás el archivo Excel que hemos
cargado, tal como se muestra en la siguiente captura de pantalla:

Eso es todo. Hemos desarrollado una aplicación que carga el blob.

Cómo funciona...
En esta receta, hemos creado una aplicación de consola que utiliza ensamblados
de almacenamiento para cargar un blob (en nuestro caso, un archivo de Excel) en
el contenedor de blobs designado. Ten en cuenta que, cada vez que se ejecute la
aplicación, se creará un nuevo archivo en el contenedor de blobs. Con el fin de cargar
los archivos de Excel con nombres únicos, vamos a anexar un GUID.

[ 222 ]
Capítulo 8

Y eso no es todo…
Anota las convenciones de nomenclatura que se deben seguir al crear el contenedor
de blobs:

En el momento de la escritura, el portal mostrará el siguiente mensaje de


error si no respetas las reglas de nomenclatura: Este nombre solo puede
contener letras minúsculas, números y guiones y debe empezar por una
letra o un número. Cada guion debe estar precedido y seguido de un
carácter distinto del guion. Además, el nombre debe tener entre 3 y 63
caracteres.

Crear un desencadenador de blob


En esta receta, vamos a crear una aplicación de función con el runtime de Azure
Functions V2, así como a descubrir cómo crear un desencadenador de blob mediante
Visual Studio. También vamos a ver cómo se activa el desencadenador de blob
cuando el archivo de Excel se carga correctamente en el contenedor de blobs.

Preparación
Establece los siguientes requisitos previos:

1. Añade un nuevo proyecto denominado ExcelImport.DurableFunctions


a la solución existente. Para ello, elige la plantilla de Azure Functions, tal
como se muestra en la siguiente captura de pantalla:

[ 223 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

2. El siguiente paso es seleccionar el runtime de Azure Functions, así como


el desencadenador. Selecciona Azure Functions v2 (.NET Core), elige
desencadenador de blob y proporciona la siguiente información:

°° Cuenta de almacenamiento (AzureWebJobsStorage): el nombre de


la cuenta de almacenamiento en la que reside el contenedor de blobs

°° Configuración de cadena de conexión: el nombre de clave


de la cadena de conexión que hace referencia a la cuenta de
almacenamiento
°° Ruta: el nombre del contenedor de blobs en el que se cargan los
archivos de Excel

[ 224 ]
Capítulo 8

3. Cuando crees el proyecto, la estructura debe tener un aspecto similar


a la siguiente captura de pantalla:

4. Vamos a añadir una cadena de conexión denominada StorageConnection


(recuerda que la hemos utilizado en el archivo de configuración de la cadena
de conexión en uno de los pasos anteriores) a local.settings.json, tal
como se muestra en la siguiente captura de pantalla:

5. Abre el archivo Function1.cs y cámbiale el nombre por


ExcelImportBlobTrigger. Asimismo, sustituye Function1 (el nombre de la
función) por ExcelImportBlobTrigger (línea 10), tal como se muestra en la
siguiente captura de pantalla:

[ 225 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

6. Configura ExcelImport.DurableFunctions como proyecto


predeterminado, tal como se muestra en la siguiente captura de pantalla:

7. Define un punto de interrupción en ExcelImportBlobTrigger y


ejecuta la aplicación. Para ello, pulsa la tecla F5. Si todo está configurado
correctamente, en la consola debería aparecer lo siguiente:

[ 226 ]
Capítulo 8

8. Vamos a cargar un nuevo archivo mediante la ejecución de la aplicación


ExcelImport.Client. Inmediatamente después de cargar el archivo,
se iniciará el desencadenador de blob, tal como se muestra en la siguiente
captura de pantalla. Los puntos de interrupción se deben alcanzar junto con
lo siguiente:

Ya hemos creado el desencadenador de blob que se inicia cuando se añade un nuevo


blob al contenedor de blobs.

Cómo hacerlo...
En esta receta, hemos creado una nueva aplicación de función basada en el runtime
de Azure Functions V2, que se basa en el marco de .NET Core y se puede ejecutar en
todas las plataformas compatibles con .NET Core (como Windows y Linux OSes).
También hemos creado un desencadenador de blob y lo hemos configurado para que
se ejecute cuando se añade un nuevo blob mediante la configuración de la cadena de
conexión. Además, hemos creado un archivo de configuración local.setting.json
para almacenar los valores de configuración que se utilizan en el desarrollo local.
Tras crear el desencadenador de blob, hemos ejecutado la aplicación ExcelImport.
Client para cargar un archivo y validar que se ejecuta el desencadenador de blob.

Y eso no es todo…
Todas las configuraciones se obtendrán del archivo local.settings.json al
ejecutar las funciones en el entorno local. Sin embargo, cuando implementes las
funciones en Azure, la referencia a los elementos de configuración (como la cadena
de conexión y la configuración de la aplicación) se obtendrá de la configuración de
la aplicación de la aplicación de función. Asegúrate de crear todos los elementos de
configuración de la aplicación de función después de implementar las funciones.

[ 227 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

Crear el orquestador durable y activarlo


para cada importación de Excel
Esta receta es una de las más importantes e interesantes. Vamos a aprender a crear
el orquestador durable encargado de gestionar las funciones de actividad que
creemos para las distintas tareas individuales necesarias para completar el proyecto
ExcelImport.

Cómo hacerlo...
Sigue estos pasos:

1. Crea una nueva función. Para ello, haz clic en ExcelImport.


DurableFunctions y en Agregar, y selecciona Nueva función de Azure, tal
como se muestra en la siguiente captura de pantalla:

2. En la ventana emergente Agregar nuevo elemento, selecciona Función de


Azure, escribe el nombre ExcelImport_Orchestrator y haz clic en Agregar, tal
como se muestra en la siguiente captura de pantalla:

[ 228 ]
Capítulo 8

3. En la ventana emergente Nueva función de Azure, selecciona la plantilla de


orquestación de Durable Functions y haz clic en el botón Aceptar, que crea
lo siguiente:

°° HttpStart: se trata de la función de inicio de Durable Functions


(un desencadenador de HTTP), que funciona como un cliente que
invoca el orquestador durable. Sin embargo, en nuestro proyecto,
no utilizaremos este desencadenador de HTTP. En su lugar,
usaremos su lógica interna en nuestro desencadenador de blob
ExcelImportBlobTrigger para invocar el orquestador durable.
°° RunOrchestrator: se trata del orquestador durable que puede
invocar y gestionar las funciones de actividad.
°° SayHello: se trata de una función de actividad sencilla, de las que
vamos a crear unas cuantas. Elimina el siguiente método:

[ 229 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

4. En el desencadenador de blob ExcelImportBlobTrigger, vamos a aplicar


los siguientes cambios al código para invocar el orquestador.

°° Configura la función para que sea asíncrona.


°° Añade los enlaces de salida del cliente de orquestación.
°° Llama a StartNewAsync mediante DurableOrchestrationClient.

5. El código de la función ExcelImportBlobTrigger debe tener el siguiente


aspecto tras aplicar los cambios:
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
namespace ExcelImport.DurableFunctions
{
public static class ExcelImportBlobTrigger
{
[FunctionName(“ExcelImportBlobTrigger”)]
public static async void Run(
[BlobTrigger(“Excelimports/{name}”, Connection =
“StorageConnection”)]Stream myBlob,
string name,
[OrchestrationClient]DurableOrchestrationClient starter,
ILogger log)
{
string instanceId = await starter.StartNewAsync(“ExcelImport_
Orchestrator”, name);
log.LogInformation($”C# Blob trigger function Processed blob\n
Name:{name} \n Size: {myBlob.Length} Bytes”);
}
}
}

6. Define un punto de interrupción en la función de orquestador ExcelImport_


Orchestrator y ejecuta la aplicación mediante la tecla F5.

[ 230 ]
Capítulo 8

7. Vamos a cargar un archivo nuevo (mientras se ejecuta ExcelImport.


DurableFunctions) mediante la ejecución de la función ExcelImport.
Client. También puedes cargar el archivo de Excel directamente desde
Azure Portal. Tras cargar el archivo y transcurridos unos momentos, se
debería alcanzar el punto de interrupción de la función ExcelImport_
Orchestrator, tal como se muestra en la siguiente captura de pantalla:

Hemos aprendido a invocar la función de orquestación duradera desde el


desencadenador de blob.

Cómo funciona...
Hemos comenzado la receta mediante la creación de la función de orquestación
y hemos aplicado cambios al desencadenador de blob ExcelImportBlobTrigger
mediante la adición de enlaces de salida OrchestratonClient para invocar la
función de orquestador durable.

Cuando se crea una nueva función de orquestación, esta crea funciones de actividad.
En las próximas recetas, las eliminaremos y crearemos nuevas funciones de actividad
según nuestros requisitos.

Y eso no es todo…
En esta receta, hemos utilizado DurableOrchestrationClient, que sabe cómo
iniciar y finalizar las orquestaciones duraderas.

[ 231 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

A continuación, se indican algunas de las operaciones importantes que se admiten:

• Iniciar una instancia mediante el método StartNewAsync


• Finalizar una instancia mediante el método TerminateAsync
• Consultar el estado de la instancia en ejecución mediante el método
GetStatusAsync
• También puede generar un evento en la instancia para actualizar los eventos
externos mediante el método RaiseEventAsync

Puedes ver más información sobre esto en https://docs.


microsoft.com/en-us/azure/azure-functions/durable-
functions-instance-management#sending-events-to-
instances.

Leer datos de Excel mediante funciones


de actividad
En esta receta, recuperaremos todos los datos de hojas de Excel específicas mediante
la escritura de una función de actividad.
Vamos a aplicar unos cambios al código de la función de orquestación mediante la
escritura de una nueva función de actividad que pueda leer los datos de una hoja de
Excel que se cargue en el contenedor de blobs.

Preparación
En esta receta, crearemos el desencadenador de actividad denominado
función ReadExcel_AT que lee los datos del blob almacenado en la cuenta de
almacenamiento. Este desencadenador de actividad realiza los siguientes trabajos:
Se conecta al blob mediante una función, ReadBlob, de una clase denominada
StorageManager.
1. Lee los datos del Excel mediante un componente denominado EPPlus.
Puedes obtener más información sobre este tema en https://github.com/
JanKallman/EPPlus.
2. Devuelve los datos del archivo de Excel en forma de colección de objetos de
empleados.
A continuación, instala los siguientes paquetes NuGet en el proyecto ExcelImport.
DurableFunctions:

Install-Package WindowsAzure.Storage
Install-Package EPPlus

[ 232 ]
Capítulo 8

Cómo hacerlo...
Si nos planteamos que Durable Functions es un flujo de trabajo, la función de
desencadenador de actividad se puede considerar un paso del flujo de trabajo que
obtiene información de entrada opcional, realiza una funcionalidad y produce
información de salida opcional. Es uno de los conceptos fundamentales de Durable
Functions de Azure.

Puedes obtener más información sobre el desencadenador de actividad


en https://docs.microsoft.com/en-us/azure/azure-
functions/durable-functions-types-features-overview.

Antes de empezar a crear la función de desencadenador de actividad, vamos a crear


las funciones de dependencia.

Leer datos de Blob Storage


Sigue estos pasos:

1. Crea una clase denominada StorageManager y pégala en el siguiente código.


Este código se conecta a la cuenta de almacenamiento especificada, lee los
datos de los blobs y devuelve un objeto stream a la función de autor de la
llamada:
class StorageManager
{
public async Task<Stream> ReadBlob(string BlobName)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(“local.settings.json”, optional: true,
reloadOnChange: true);
IConfigurationRoot configuration = builder.Build();
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.
Parse(configuration.GetConnectionString(“StorageConnection”));
CloudBlobClient cloudBlobClient = cloudStorageAccount.
CreateCloudBlobClient();
CloudBlobContainer ExcelBlobContainer = cloudBlobClient.
GetContainerReference(“Excel”);
CloudBlockBlob cloudBlockBlob = ExcelBlobContainer.GetBlockBlobRe
ference(BlobName);
return await cloudBlockBlob.OpenReadAsync();
}
}

[ 233 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

2. Pega las siguientes referencias de espacio de nombres en la clase


StorageManager:
using Microsoft.Extensions.Configuration;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System.IO;
using System.Threading.Tasks;
3. Por último, añade una cadena de conexión (si no lo has hecho ya) de la
cuenta de almacenamiento al archivo local.settings.json, tal como se
muestra aquí:

Leer datos de Excel desde la secuencia


Sigue estos pasos:
1. Crea una clase denominada EPPLusExcelManager y pégala en el siguiente
código. Esta clase tiene un método denominado ReadExcelData, que utiliza
una biblioteca llamada EPPlus para leer los datos del archivo de Excel
(extensión.xlsx). Lee todas las filas, crea un objeto Employee para cada fila y
devuelve una colección de empleados. Vamos a crear la clase Employee en un
momento:
class EPPLusExcelManager
{
public List<Employee> ReadExcelData(Stream stream)
{
List<Employee> employees = new List<Employee>();
//FileInfo existingFile = new FileInfo(“EmployeeInformation.
xlsx”);
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet ExcelWorksheet = package.Workbook.Worksheets[0];
for (int EmployeeIndex = 2; EmployeeIndex < ExcelWorksheet.
Dimension.Rows + 1; EmployeeIndex++)
{

[ 234 ]
Capítulo 8

employees.Add(new Employee()
{
EmpId = Convert.ToString(ExcelWorksheet.Cells[EmployeeIndex,
1].Value),
Name = Convert.ToString(ExcelWorksheet.Cells[EmployeeIndex,
2].Value),
Email = Convert.ToString(ExcelWorksheet.Cells[EmployeeIndex,
3].Value),
PhoneNumber = Convert.ToString(ExcelWorksheet.
Cells[EmployeeIndex, 4].Value)
});
}
}
return employees;
}
}
2. Vamos a crear otra clase denominada Employee y a copiar el siguiente
código:
public class Employee
{
public string EmpId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
}

Si compilas la aplicación ahora, no debería producirse ningún error. Ya hemos


terminado el desarrollo de las dependencias para nuestra primera función de
desencadenador de actividad. Ahora vamos a empezar a crear el desencadenador
de actividad.

Crear la función de actividad


Sigue estos pasos:

1. Crea una función de actividad denominada ReadExcel_AT que se conecte al


blob mediante la clase StorageManager que hemos desarrollado en la sección
anterior y que después lea los datos mediante la clase EPPLusExcelManager.
Copia el siguiente código en la clase ExcelImport_Orchestrator:
[FunctionName(“ReadExcel_AT”)]
public static async Task<List<Employee>> ReadExcel_AT(
[ActivityTrigger] string name,
ILogger log)
{

[ 235 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

log.LogInformation(“Orchestration started”);
StorageManager storageManager = new StorageManager();
Stream stream = null; ;
log.LogInformation(“Reading the Blob Started”);
stream = await storageManager.ReadBlob(name);
log.LogInformation(“Reading the Blob has Completed”);
EPPLusExcelManager ePPLusExcelManager = new EPPLusExcelManager();
log.LogInformation(“Reading the Excel Data Started”);
List<Employee> employees = ePPLusExcelManager.
ReadExcelData(stream);
log.LogInformation(“Reading the Blob has Completed”);
return employees;
}

2. Si no existe, añade System.IO a la lista de espacios de nombres y compila la


aplicación.
3. Vamos a invocar esta función de actividad desde el orquestador. Ve a la
función de orquestador ExcelImport_Orchestrator y sustitúyela por el
siguiente código. La función de orquestación invoca la función de actividad.
Para ello, pasa el nombre del Excel que se carga para que la función de
actividad lea los datos del archivo de Excel:
[FunctionName(“ExcelImport_Orchestrator”)]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] DurableOrchestrationContext context)
{
var outputs = new List<string>();
string ExcelFileName = context.GetInput<string>();
List<Employee> employees = await context.CallActivityAsync<List<E
mployee>>(“ReadExcel_AT”, ExcelFileName);
return outputs;
}

[ 236 ]
Capítulo 8

4. Vamos a ejecutar la aplicación y después cargaremos un archivo de Excel. Si


todo está configurado correctamente, deberías ver algo parecido a lo que se
muestra en la función de desencadenador de actividad ReadExcel_AT, donde
aparece el número de registros de empleados que se leen desde la hoja de
Excel:

Y eso no es todo…
La función de orquestador recibe la información de entrada mediante el método
GetInput() de la clase DurableOrchestratorContext. Esta información de
entrada la pasa el desencadenador de blob mediante el método de función
StartNewAsync de la clase DurableOrchestrationClient.

[ 237 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

Escalar automáticamente el rendimiento


de Cosmos DB
En la receta anterior, hemos leído los datos de Excel y los hemos puesto en una
colección de empleados. El siguiente paso es insertar la colección en una colección de
Cosmos DB. Sin embargo, antes de insertar los datos en la colección de Cosmos DB,
debemos entender que en situaciones reales, el número de registros que tendríamos
que importar sería enorme. Por ello, podrías enfrentarte a problemas de rendimiento
si la capacidad de la colección de Cosmos DB no es suficiente.

El rendimiento de la colección de Cosmos DB se mide mediante el


número de unidades de solicitud (RU) asignadas a la colección.
Puedes obtener más información sobre este tema en https://docs.
microsoft.com/en-us/azure/cosmos-db/request-units.

Además, con el fin de reducir los costes de cada servicio, se recomienda que la
capacidad sea inferior y se amplíe conforme sea necesario. La API de Cosmos DB
nos permite controlar el número de RU en función de nuestras necesidades. Como
necesitamos hacer una importación masiva, aumentaremos las RU antes de empezar
a importar los datos. Una vez finalizado el proceso de importación, podemos reducir
las RU al mínimo.

Preparación
Establece los siguientes requisitos previos:

1. Crea una cuenta de Cosmos DB con las instrucciones indicadas en el artículo


de https://docs.microsoft.com/en-us/azure/cosmos-db/create-sql-
api-dotnet.

[ 238 ]
Capítulo 8

2. Crea una base de datos de Cosmos DB y una colección con almacenamiento


fijo y establece las unidades de solicitud en 400 por segundo, tal como se
muestra en la siguiente captura de pantalla:

Para simplificar la tarea, he establecido Fija (10 GB) como Capacidad de


almacenamiento. Sin embargo, en cargas de producción, en función de
los modelos de datos, es posible que debas establecer una capacidad de
almacenamiento Ilimitada.
3. Ejecuta el siguiente comando en el administrador de paquetes NuGet para
instalar las dependencias de Cosmos DB:
Install-Package Microsoft.Azure.WebJobs.Extensions.CosmosDB

[ 239 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

Cómo hacerlo...
Sigue estos pasos:

1. Crea un nuevo desencadenador de actividad denominado ScaleRU_AT en el


archivo ExcelImport_Orchestrator.cs. La función debe tener un aspecto
similar. Acepta que el número de RU se pueda aumentar, junto con el enlace
de Cosmos DB con el que hemos sustituido el rendimiento:
[FunctionName(“ScaleRU_AT”)]
public static async Task<string> ScaleRU_AT(
[ActivityTrigger] int RequestUnits,
[CosmosDB(ConnectionStringSetting = “CosmosDBConnectionString”)]
DocumentClient client
)
{
DocumentCollection EmployeeCollection = await client.ReadDocumen
tCollectionAsync(UriFactory.CreateDocumentCollectionUri(“cookbook
db”, “EmployeeCollection”));
Offer offer = client.CreateOfferQuery().Where(o => o.ResourceLink
== EmployeeCollection.SelfLink).AsEnumerable().Single();
Offer replaced = await client.ReplaceOfferAsync(new
OfferV2(offer, RequestUnits));
return $”The RUs are scaled to 500 RUs!”;
}

2. Añade los siguientes espacios de nombres al archivo ExcelImport_


Orchestrator.cs:

using System.Linq;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;

[ 240 ]
Capítulo 8

3. Crea una nueva cadena de conexión para Cosmos DB, tal como se muestra
en la siguiente captura de pantalla. Puedes copiar la conexión desde la hoja
Claves de la cuenta de Cosmos DB:

4. En la función ExcelImport_Orchestrator, añade la siguiente línea para


invocar ScaleRU_AT. En este ejemplo, he utilizado 500 como valor de RU.
En función de tus necesidades, puedes elegir un valor diferente:
await context.CallActivityAsync<string>(“ScaleRU_AT”, 500);

5. Carga un archivo de Excel para activar la orquestación, que invoca


internamente el nuevo desencadenador de actividad, ScaleRU_AT. Si todo
ha ido bien, la nueva capacidad de la colección de Cosmos DB debe ser 500.
Vayamos a la pestaña Explorador de datos de Cosmos DB, a la sección de
escala y configuración, donde verás 500 como nuevo rendimiento de la
colección, tal como se muestra a continuación:

[ 241 ]
Importación masiva de datos mediante Cosmos DB y Durable Functions de Azure

Y eso no es todo…
La capacidad de la colección de Cosmos DB se representa en forma de recurso
denominado oferta. En esta receta, hemos recuperado la oferta existente y la hemos
sustituido por una nueva. Puedes ver más información sobre el tema en https://
docs.microsoft.com/en-us/rest/api/cosmos-db/offers.

Insertar masivamente datos


en Cosmos DB
Ya hemos aumentado el tamaño de la colección. Ahora vamos a insertar los datos
en la colección de Cosmos DB. Para que esta receta sea fácil y directa, aprenderemos
una de las formas más sencillas de insertar datos en Cosmos DB.

Cómo hacerlo...
Sigue estos pasos:

1. Crea un nuevo desencadenador de actividad denominado ImportData_


AT, que utiliza la colección de empleados como información de entrada
y guarda los datos en la colección. Pega el siguiente código en el nuevo
desencadenador de actividad:
[FunctionName(“ImportData_AT”)]
public static async Task<string> ImportData_AT(
[ActivityTrigger] List<Employee> employees,
[CosmosDB(ConnectionStringSetting = “CosmosDBConnectionString”)]
DocumentClient client,
ILogger log)
{
foreach (Employee employee in employees)
{
await client.CreateDocumentAsync(UriFactory.CreateDocumentCollect
ionUri(“cookbookdb”, “EmployeeCollection”), employee);
log.LogInformation($”Successfully inserted {employee.Name}.”);
}
return $”Data has been imported to Cosmos DB Collection
Successfully!”;
}

2. Vamos a añadir la siguiente línea a la función de orquestación que invoca el


desencadenador de actividad ImportData_AT:
await context.CallActivityAsync<string>(“ImportData_AT”,
employees);

[ 242 ]
Capítulo 8

Vamos a ejecutar la aplicación y a cargar un archivo de Excel para probar la


funcionalidad. Si todo ha ido bien, deberías ver los registros creados en la
colección de Cosmos DB, tal como se muestra a continuación:

Y eso no es todo…
El equipo de Cosmos DB ha publicado una biblioteca denominada Cosmos DB Bulk
Executor. Puedes ver más información sobre el tema en https://docs.microsoft.
com/en-us/azure/cosmos-db/bulk-executor-overview.

En esta receta, he codificado de forma rígida el nombre de la colección y la base


de datos para simplificar la tarea. Tendrás que configurarlos en el archivo de
configuración de la aplicación.

[ 243 ]
Implementar prácticas
recomendadas para
Azure Functions
En este capítulo, aprenderás algunas de las prácticas recomendadas para trabajar con
Azure Functions, entre ellas:

• Agregar varios mensajes a una cola mediante la función IAsyncCollector


• Implementar aplicaciones defensivas con Azure Functions
y desencadenadores de cola
• Administrar entradas masivas mediante Event Hubs para IoT y otros
escenarios similares
• Evitar arranques en frío activando la aplicación periódicamente
• Habilitar autorización para aplicaciones de función
• Controlar el acceso a Azure Functions mediante claves de función
• Proteger Azure Functions mediante Azure Active Directory
• Configurar la limitación de Azure Functions mediante API Management
• Acceder de forma segura a SQL Database desde Azure Functions mediante
Managed Service Identity
• Código compartido en Azure Functions mediante bibliotecas de clases
• Usar clases fuertemente tipadas en Azure Functions

[ 244 ]
Capítulo 9

Agregar varios mensajes a una cola


mediante la función IAsyncCollector
En el primer capítulo, has aprendido a crear un mensaje de cola para cada solicitud
procedente de la solicitud HTTP. Ahora supongamos que cada usuario va
a registrar su dispositivo mediante aplicaciones cliente (como aplicaciones de
escritorio, aplicaciones móviles o cualquier sitio web de cliente) que pueden enviar
varios registros en una sola solicitud. En estos casos, la aplicación de back-end debe
ser lo suficientemente inteligente como para manejar la carga que le llega; debe
existir un mecanismo que permita crear varios mensajes de cola a la vez y de forma
asincrónica. Aprenderás a crear varios mensajes de cola mediante la
interfaz IAsyncCollector.

A continuación, se muestra un diagrama que representa el flujo de datos desde


diferentes aplicaciones cliente a la API web de back-end:

En esta receta, vamos a simular las solicitudes mediante Postman, que enviará la
solicitud a la API web de back-end (HTTPTrigger), que puede crear todos los
mensajes de cola de una sola vez.

Preparación
Estos son los pasos necesarios:

1. Crea una cuenta de almacenamiento mediante Azure Portal si aún


no lo has hecho
2. Instala el explorador de Microsoft Azure Storage desde http://
storageexplorer.com/ si aún no lo has instalado
[ 245 ]
Implementar prácticas recomendadas para Azure Functions

Cómo hacerlo...
Sigue estos pasos:

1. Crea un nuevo desencadenador de HTTP denominado


BulkDeviceRegistrations y establece el nivel de autorización en Anónimo.
2. Reemplaza el código predeterminado por el siguiente código y haz clic en
el botón Guardar para guardar los cambios. El código siguiente espera una
matriz JSON como un parámetro de entrada con un atributo denominado
"devices". Si se encuentra, se repetirá a través de los elementos de la matriz
y, a continuación, los mostrará en los registros. Más adelante, modificaremos
el programa para insertar de forma masiva los elementos de la matriz en el
mensaje de cola:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req,
ILogger log )
{
log.LogInformation("C# HTTP trigger function processed a
request.");
string requestBody = await new StreamReader(req.Body).
ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string Device = string.Empty;
for(int nIndex=0;nIndex<data.devices.Count;nIndex++)
{
Device = Convert.ToString(data.devices[nIndex]);
log.LogInformation("devices data" + Device);
}
return (ActionResult)new OkObjectResult("Program has been executed
Successfully.");
}

3. El siguiente paso es crear un enlace de salida de Azure Queue Storage. Haz


clic en el botón Guardar, ve a la pestaña Integrar y agrega un nuevo enlace
de salida de Azure Queue Storage. A continuación, haz clic en el botón
Seleccionar y proporciona el nombre de la cola y otros parámetros.

[ 246 ]
Capítulo 9

4. Haz clic en el botón Guardar y ve al editor de código de la Azure Function.


Agrega el código adicional necesario para el enlace de salida con la cola para
guardar los mensajes, como se muestra en el código siguiente. Realiza los
cambios resaltados en el editor de código y haz clic en el botón Guardar para
guardar los cambios:
public static async Task<IActionResult> Run(HttpRequest req,
ILogger log,
IAsyncCollector<string> DeviceQueue )
{
....
....
for(int nIndex=0;nIndex<data.devices.Count;nIndex++)
{
Device = Convert.ToString(data.devices[nIndex]);
DeviceQueue.AddAsync(Device); }
....
....

5. Vamos a ejecutar la función desde la pestaña Prueba del portal con el


siguiente JSON de solicitud de entrada:
{
"devices":
[
{
"type": "laptop",
"brand":"lenovo",
"model":"T440"
},
{
"type": "mobile",
"brand":"Mi",
"model":"Red Mi 4"
}
]
}

6. Haz clic en el botón Ejecutar para probar la funcionalidad. Ahora abre el


explorador de Azure Storage y ve a la cola denominada "devicequeue".
Como se muestra en la siguiente captura de pantalla, deben aparecer
dos registros:

[ 247 ]
Implementar prácticas recomendadas para Azure Functions

Cómo funciona...
Hemos creado una nueva función HTTP que tiene un parámetro del tipo
IAsyncCollector<string>, que se puede utilizar para almacenar varios mensajes
en un servicio de cola a la vez y de forma asincrónica. Este procedimiento para
almacenar varios elementos de forma asincrónica reducirá la carga en las instancias.

Por último, hemos probado la invocación del desencadenador de HTTP desde Azure
Portal y hemos visto asimismo que los mensajes de la cola se ha podido agregar
mediante el explorador de Azure Storage.

Y eso no es todo…
También puedes utilizar la interfaz ICollector, en lugar de IAsyncCollector,
si deseas almacenar varios mensajes de forma asincrónica.

Ten en cuenta que es posible que tengas que instalar extensiones


de Azure Storage para agregar enlaces de salida si todavía no lo
has hecho. En el runtime de Azure Functions v2, es obligatorio
agregar extensiones a cada uno de los servicios (almacenamiento,
en este caso).

Implementar aplicaciones defensivas con


Azure Functions y desencadenadores
de cola
Para muchas aplicaciones, incluso después de realizar varias pruebas de diferentes
entornos, podrían seguir existiendo motivos de posibles errores en la aplicación.
Los desarrolladores y arquitectos no pueden predecir todas las entradas imprevistas
durante la vida útil de una aplicación utilizada por usuarios profesionales o usuarios
generales finales. Por lo tanto, es recomendable asegurarse de que la aplicación te
notifica cualquier error o problema imprevisto en las aplicaciones.
[ 248 ]
Capítulo 9

En esta receta, aprenderás cómo nos ayuda Azure Functions a controlar este tipo de
problemas con un código mínimo.

Preparación
Estos son los pasos necesarios:
1. Crear una cuenta de almacenamiento mediante Azure Portal si aún
no lo has hecho
2. Instalar el explorador de Azure Storage desde http://storageexplorer.
com/ si aún no lo has instalado

Cómo hacerlo...
En esta receta, haremos lo siguiente:
• Desarrollar una aplicación de consola con C# que se conecte a la cuenta
de almacenamiento y cree mensajes de cola en la cola denominada
myqueuemessages
• Crear un desencadenador de cola de la Azure Function denominada
ProcessData que se active cada vez que se agregue un mensaje nuevo a la
cola denominada myqueuemessages

CreateQueueMessage: aplicación de consola de C#


Sigue estos pasos:
1. Crea una nueva aplicación de consola con el lenguaje C# de .NET
Core y crea una clave de configuración de la aplicación denominada
StorageConnectionString con la cadena de conexión de la cuenta de
almacenamiento. Puedes obtener la cadena de conexión de la hoja Claves de
acceso de la cuenta de almacenamiento, tal como se muestra:

2. Instala los paquetes NuGet de Configuración y Almacenamiento de cola


utilizando los siguientes comandos:
Install-Package Microsoft.Azure.Storage.Queue
Install-Package System.Configuration.ConfigurationManager

3. Agrega los siguientes espacios de nombres:


using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
using System.Configuration;
[ 249 ]
Implementar prácticas recomendadas para Azure Functions

4. Agrega la siguiente función a la aplicación de consola y llámala desde el


método Main. La función CreateQueueMessages crea 100 mensajes con el
índice como contenido de cada mensaje:
static void CreateQueueMessages()
{
CloudStorageAccount storageAccount =
CloudStorageAccount.Parse(ConfigurationManager.
AppSettings
["StorageConnectionString"]);
CloudQueueClient queueclient =
storageAccount.CreateCloudQueueClient();

CloudQueue queue = queueclient.GetQueueReference


("myqueuemessages");
queue.CreateIfNotExists();

CloudQueueMessage message = null;


for(int nQueueMessageIndex = 0; nQueueMessageIndex <=
100;
nQueueMessageIndex++)
{
message = new CloudQueueMessage(Convert.ToString
(nQueueMessageIndex));
queue.AddMessage(message);
Console.WriteLine(nQueueMessageIndex);
}
}

Desarrollar la Azure Function: desencadenador


de cola
Sigue estos pasos:

1. Crea una función de Azure nueva denominada ProcessData mediante el


desencadenador de cola y configura la cola myqueuemessages. Así es como
debe mostrarse la pestaña Integrar una vez creada la función:

[ 250 ]
Capítulo 9

2. Reemplaza el código predeterminado por el código siguiente:


using System;
public static void Run(string myQueueItem,
ILogger log)
{
if(Convert.ToInt32(myQueueItem)>50)
{
throw new Exception(myQueueItem);
}
else
{
log.LogInformation($"C# Queue trigger function
processed: {myQueueItem}");
}
}

El desencadenador de cola anterior registra un mensaje con el contenido de la cola


(es solo un índice numérico) para los primeros 50 mensajes y, a continuación, genera
una excepción para todos los mensajes cuyo contenido es mayor que 50.

Ejecutar pruebas mediante la aplicación de consola


Sigue estos pasos:

1. Vamos a ejecutar la aplicación de consola. Para ello, pulsa Ctrl + F5, ve al


explorador de Azure Storage y revisa el contenido de la cola.
2. En apenas unos instantes, deberían mostrarse los mensajes de la cola
myqueuemessages. Actualmente, tanto Azure Portal como el explorador de
Azure Storage muestran los primeros 32 mensajes. Debes usar el Storage SDK
de C# para ver todos los mensajes de la cola.

No te sorprendas si observas que los mensajes de la myqueuemessage


están desapareciendo. Una vez leído correctamente un mensaje, este se
elimina de la cola.

3. Como se muestra aquí, también debería aparecer una cola nueva


denominada myqueuemessages-poison (<OriginalQueuename>-Poison)
con los otros 50 mensajes de la cola en ella. El runtime de Azure Function se
encargará de crear automáticamente una nueva cola y agregar los mensajes
que Azure Functions no haya leído correctamente:

[ 251 ]
Implementar prácticas recomendadas para Azure Functions

Cómo funciona...
Hemos creado una aplicación de consola que crea mensajes en Azure Queue Storage
y también hemos desarrollado un desencadenador de cola que es capaz de leer los
mensajes de la cola. Como parte de la simulación de un error imprevisto, hemos
hecho que se genere un error si el valor del contenido del mensaje de cola es mayor
que 50.

Azure Functions se encargará de crear una nueva cola con el nombre


<OriginalQueueName>-Poison e insertará todos los mensajes sin procesar en la
nueva cola. Con esta nueva cola de daños, los desarrolladores pueden revisar el
contenido de los mensajes y tomar las medidas necesarias para corregir errores
en las aplicaciones.

El runtime de Azure Function se encargará de eliminar el mensaje de cola una vez


que se haya completado correctamente la ejecución de dicha función. Si hay algún
problema en la ejecución de la Azure Function, crea automáticamente una nueva cola
de daños y agrega los mensajes procesados a la nueva cola.

Y eso no es todo…
Antes de insertar un mensaje de cola en la cola de daños, el runtime de Azure
Function intenta seleccionar el mensaje y procesarlo cinco veces. Puedes obtener
información sobre cómo funciona este proceso si agregas un nuevo parámetro
dequecount del tipo int al método Run y registras su valor.

[ 252 ]
Capítulo 9

Administrar entradas masivas


mediante Event Hubs para IoT y otros
escenarios similares
En muchos casos, es posible que necesites controlar grandes cantidades de datos
entrantes. Los datos entrantes pueden proceder de sensores y datos de telemetría,
y pueden ser simplemente los datos enviados por dispositivos con Fitbit. En estas
situaciones, necesitamos contar con una solución fiable que sea capaz de administrar
cantidades masivas de datos. Azure Event Hubs es una de las soluciones que
proporciona Azure. En esta receta, aprenderás cómo integrar Event Hubs
y Azure Functions.

Preparación
Sigue estos pasos:
1. Crea un espacio de nombres de Event Hubs. Para ello, ve al Internet de las
cosas y selecciona Event Hubs.
2. Una vez creado el espacio de nombres de Event Hubs, ve la pestaña
Información general y haz clic en el icono Centro de eventos para crear un
Centro de eventos nuevo.
3. De forma predeterminada, se creará un Grupo de consumidores
denominado $Default, que es el que vamos a utilizar en esta receta.

Cómo hacerlo...
En esta receta, vamos a seguir estos pasos:
• Crear un desencadenador de centro de eventos de la Azure Function
• Desarrollar una aplicación de consola que simule los datos del Internet de
las cosas (IoT)
Crear un desencadenador de centro de eventos
de la Azure Function
Sigue estos pasos:
1. Para crear una nueva función de Azure, selecciona Desencadenador de
centro de eventos en la lista de plantillas.
2. Una vez seleccionada la plantilla, es posible que tengas que instalar las
extensiones. A continuación, deberás proporcionar el nombre del centro
de eventos, capturemessage. Si aún no has configurado ninguna conexión,
haz clic en el botón Nueva.
3. Al hacer clic en el botón Nueva, se abrirá una ventana emergente de
Conexión en la que puedes seleccionar el Centro de eventos y otros datos.
Selecciona los datos solicitados y haz clic en el botón Seleccionar, como se
muestra en la siguiente captura de pantalla:
[ 253 ]
Implementar prácticas recomendadas para Azure Functions

4. El paso anterior rellenará el menú desplegable de Conexión del centro de


eventos. Por último, haz clic en Crear para crear la función.

Desarrollar una aplicación de consola que


simule los datos de IoT
Sigue estos pasos:

1. Crea una nueva aplicación de consola que se encargue de enviar eventos al


centro de eventos. Yo la he nombrado EventHubApp.
2. Ejecuta los siguientes comandos en el administrador de paquetes de NuGet
para instalar las bibliotecas necesarias e interactuar con Azure Event Hubs:
Install-Package Microsoft.Azure.EventHubs
Install-Package Newtonsoft.Json

3. Agrega los siguientes espacios de nombres y una referencia a System.


Configuration.dll:
using Microsoft.Azure.EventHubs;
using System.Configuration;

4. Agrega la cadena de conexión a App.config, que se utiliza para conectar


el centro de eventos. Este es el código para App.config. Para obtener la
cadena de conexión, haz clic en el enlace ConnectionStrings de la pestaña
Información general del espacio de nombres del centro de eventos:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.6.1" />
</startup>
<appSettings>
<add key="EventHubConnection"

[ 254 ]
Capítulo 9

value="Endpoint=sb://<event hub namespace


here>.servicebus.windows.net/;Entitypath=<Event
Hubname>;
SharedAccessKeyName= RootManageSharedAccessKey;
SharedAccessKey=<Key here>"/>
</appSettings>
</configuration>
5. Crea un nuevo archivo de clase de C# y coloca el código siguiente en el
nuevo archivo de clase:
using System;
using System.Text;
using Microsoft.Azure.EventHubs;
using System.Configuration;
using System.Threading.Tasks;

namespace EventHubApp
{
class EventHubHelper
{
static EventHubClient eventHubClient = null;
public static async Task GenerateEventHubMessages()
{

EventHubsConnectionStringBuilder conBuilder = new


EventHubsConnectionStringBuilder
(ConfigurationManager.AppSettings
["EventHubConnection"].ToString());

eventHubClient =
EventHubClient.CreateFromConnectionString
(conBuilder.ToString());
string strMessage = string.Empty;
for (int nEventIndex = 0; nEventIndex <= 100;
nEventIndex++)
{
strMessage = Convert.ToString(nEventIndex);
await eventHubClient.SendAsync(new EventData
(Encoding.UTF8.GetBytes(strMessage)));
Console.WriteLine(strMessage);
}
await eventHubClient.CloseAsync();
}
}
}
6. En tu función principal, coloca el siguiente código, que invoca el método
para enviar el mensaje:
namespace EventHubApp
{

[ 255 ]
Implementar prácticas recomendadas para Azure Functions

class Program
{
static void Main(string[] args)
{
EventHubHelper.GenerateEventHubMessages().Wait();
}
}
}

7. Ahora ejecuta la aplicación pulsando Ctrl + F5. Debería aparecer algo similar
a lo que se muestra aquí:

8. Mientras la consola imprime los números, puedes ir a la Azure Function para


comprobar si el centro de eventos se activa automáticamente y registra los
números que se están enviando al centro de eventos.

[ 256 ]
Capítulo 9

Evitar arranques en frío activando la


aplicación periódicamente
Por ahora, ya sabes que puedes crear funciones de Azure en los dos planes de
hosting siguientes:

• Plan de App Service


• Plan de consumo

Solo podrás obtener todas las ventajas de la arquitectura sin servidor si creas la
Function App mediante el plan de consumo. Sin embargo, uno de los problemas del
que han informado los desarrolladores en cuanto al uso del plan de consumo es lo
que se conoce como arranque en frío, que consiste en poner en marcha una función
de Azure para atender las solicitudes sin que se hayan recibido solicitudes desde
hace tiempo. Puedes obtener más información sobre este tema en
https://blogs.msdn.microsoft.com/appserviceteam/2018/02/07/
understanding-serverless-cold-start/.

En esta receta, aprenderemos una técnica que se podría utilizar para


mantener siempre activa la instancia, de tal modo que todas las solicitudes se
atiendan correctamente.

El plan de App Service es un plan de hosting dedicado en


el que las instancias están reservadas para ti y pueden estar
siempre activas, aunque no se reciban solicitudes durante
cierto tiempo.

Preparación
Para completar esta receta, debemos tener una aplicación de función con lo siguiente:

• Un desencadenador de HTTP denominado HttpALive


• Un desencadenador de temporizador denominado KeepFunctionAppWarm
que se ejecuta cada 5 minutos y realiza una solicitud HTTP al
desencadenador de HTTP HttpALive

Si has entendido claramente en qué consiste un arranque en frío, ya debes tener


igualmente claro que no habrá ningún problema si la aplicación ha tenido un tráfico
regular durante el día. Por lo tanto, si podemos garantizar que la aplicación tiene
tráfico durante todo el día, la instancia de la Azure Function no se desaprovisionará
y, por lo tanto, tampoco debe haber problema ninguno con el plan de consumo.

[ 257 ]
Implementar prácticas recomendadas para Azure Functions

Cómo hacerlo...
En esta receta, vamos a crear un desencadenador de temporizador que simulará
el tráfico al desencadenador de HTTP, lo que hará que la Function App esté
permanentemente activa y las instancias sin servidor estén siempre en
estado aprovisionado.

Crear un desencadenador de HTTP


Crea un desencadenador de HTTP nuevo y reemplaza el siguiente código, que tan
solo imprime un mensaje cuando se ejecuta:
using System.Net;
using Microsoft.AspNetCore.Mvc;
public static async Task<IActionResult> Run(HttpRequest req, ILogger
log)
{
return (ActionResult)new OkObjectResult($"Hello User! Thanks for
keeping me Warm");
}

Crear un desencadenador de temporizador


Sigue estos pasos:
1. Haz clic en el icono +, busca el temporizador y haz clic en el botón
Desencadenador de temporizador.
2. En la ventana emergente Nueva función, proporciona los datos necesarios.
En este caso, la Programación es una expresión CRON que garantiza que el
desencadenador de temporizador se active automáticamente cada 5 minutos:

[ 258 ]
Capítulo 9

3. Pega el siguiente código en el editor de código y guarda los cambios. El


código siguiente simula el tráfico generando solicitudes HTTP mediante
programación. Asegúrate de reemplazar <<FunctionAppName>> con el
nombre real de la Function App:
using System;
public async static void Run(TimerInfo myTimer, ILogger log)
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync("https://<FunctionAppNa
me>>.azurewebsites.net/api/HttpALive");
}
}

Y eso no es todo…
Si experimentas un poco con Azure Functions, podrás observar que los tiempos de
arranque en frío para Azure Functions que tienen C# como lenguaje son de apenas
unos segundos. Sin embargo, si trabajas con Azure Functions que utilizan JavaScript
(como Node.js) como lenguaje, el tiempo de arranque en frío será mayor, dado que
el runtime tiene que descargar todos los paquetes de NPM que son dependencias
de la aplicación. Para estos casos hay una función, denominada Ejecutar desde
el paquete, que resulta muy útil. Vamos a aprender cómo implementar esto en el
próximo capítulo.

Consulta también
Consulta la receta Implementar Azure Functions mediante Ejecutar desde el paquete del
capítulo 10, Configurar aplicaciones sin servidor en el entorno de producción.

Habilitar autorización para aplicaciones


de función
Si la API web (desencadenador de HTTP) se está utilizando en varias aplicaciones
cliente y deseas proporcionar acceso únicamente a las aplicaciones previstas
y autorizadas, debes implementar la autorización para restringir el acceso a la
Azure Function.

Preparación
Supongo que ya sabes cómo crear una función de desencadenador de HTTP.
Puedes descargar la herramienta Postman de https://www.getpostman.com/.
La herramienta Postman se utiliza para enviar solicitudes HTTP. También puedes
utilizar cualquier herramienta o aplicación que permita enviar solicitudes
y encabezados HTTP.

[ 259 ]
Implementar prácticas recomendadas para Azure Functions

Cómo hacerlo...
Sigue estos pasos:

1. Crea una nueva función de desencadenador de HTTP (o abre una función


HTTP existente). Asegúrate de que al crear la función, seleccionas la opción
Función en el menú desplegable de nivel de Autorización.

Si deseas elegir una función de desencadenador de HTTP


existente que hayamos creado en una de las recetas anteriores,
haz clic en la pestaña Integrar, cambia el nivel de Autorización
a Función y haz clic en el botón Guardar para guardar
los cambios.

2. En la pestaña Editor de código, obtén la dirección URL de la función a través


del enlace Obtener dirección URL de la función disponible en la esquina
derecha del editor de código en el archivo run.csx.
3. Ve a Postman y pega la dirección URL de la función:

4. Observa que la dirección URL tiene las siguientes cadenas de consulta:


°° code: esta es la cadena de consulta predeterminada prevista por el
runtime de la función y valida los derechos de acceso de la función.
La funcionalidad de validación se activa automáticamente sin
necesidad de que el desarrollador escriba el código. Para que suceda
todo esto tan solo hay que establecer el nivel de Autorización
en Función.
°° name: esta es una cadena de consulta requerida por la función de
disparador HTTP.

5. Vamos a quitar la cadena de consulta de código de la dirección URL


en Postman e intentar realizar una solicitud. Se mostrará un error
401: No autorizado.

[ 260 ]
Capítulo 9

Cómo funciona...
Al realizar una solicitud a través de Postman o de cualquier otra herramienta
o aplicación que pueda enviar solicitudes HTTP, la aplicación web de Azure App
Service subyacente recibirá la solicitud (ten en cuenta que Azure Functions se basa
en App Services), que primero comprueba si está presente el código del nombre de
encabezado en la colección de cadenas de consulta o en el cuerpo de la solicitud.
Si lo encuentra, valida el valor de la cadena de consulta de código con las claves de
función. Si es válido, autoriza la solicitud y permite que el runtime la procese. De lo
contrario, se genera un error con el mensaje 401: No autorizado.

Y eso no es todo…
Ten en cuenta que la clave de seguridad (parámetro de cadena de consulta con
el nombre code) del ejemplo anterior se usa solo con fines de demostración. En
escenarios de producción, en lugar de pasar la clave como un parámetro de cadena
de consulta (el parámetro code), debes agregar la clave x-functions-key como
encabezado HTTP, como se muestra en la siguiente captura de pantalla:

Controlar el acceso a Azure Functions


mediante claves de función
Ahora ya sabes cómo habilitar la autorización de un desencadenador de HTTP
individual mediante la configuración del campo Nivel anónimo a través de la
función value en la pestaña Integrar de la función de desencadenador HTTP.
Funciona bien si tienes solamente una función de Azure como API web de back-end
para una de tus aplicaciones y no deseas restringir el acceso al público.

[ 261 ]
Implementar prácticas recomendadas para Azure Functions

Sin embargo, en las aplicaciones de nivel empresarial, terminarás desarrollando


varias Azure Functions en varias aplicaciones de función. En esos casos, debes
disponer de un nivel de acceso específico y perfectamente delimitado a la Azure
Function para tus propias aplicaciones o para aplicaciones de terceros que integren
tus API en sus aplicaciones.

En esta receta, aprenderás a trabajar con claves de función dentro


de Azure Functions.

Cómo hacerlo...
Azure es compatible con las siguientes claves, que se pueden utilizar para controlar
el acceso a Azure Functions:

• Claves de función: se pueden utilizar para otorgar permisos de autorización


a una función determinada. Estas claves son específicas de la función con la
que están asociadas.
• Claves de host: podemos usarlas para controlar la autorización de todas las
funciones dentro de una aplicación de función de Azure.

Configurar la clave de función para cada aplicación


Si vas a desarrollar una API con Azure Functions que pueden utilizar varias
aplicaciones, es recomendable tener una clave de función diferente para cada
aplicación cliente que vaya a usar las funciones.

Ve a la pestaña Administrar de Azure Functions para ver y administrar todas las


claves relacionadas con la función.

De forma predeterminada, se genera una clave con el nombre predeterminado.


Si deseas generar una clave nueva, haz clic en el botón Agregar nueva clave
de función.

Conforme a la instrucción anterior, he creado las claves para las siguientes


aplicaciones:

• WebApplication: el nombre de clave WebApplication está configurado para


utilizarse en el sitio web que utiliza la Azure Function.
• MobileApplication: el nombre de clave MobileApplication está
configurado para utilizarse en la aplicación móvil que utiliza la
Azure Function.

Del mismo modo, puedes crear diferentes claves para cualquier otra aplicación
(por ejemplo, una aplicación de IoT) en función de tus requisitos.

[ 262 ]
Capítulo 9

Al contar con diferentes claves para la misma función podrás tener control sobre
los permisos de acceso de diferentes aplicaciones para el uso de las funciones. Por
ejemplo, si deseas revocar los permisos solo a una aplicación, y no a todas ellas, tan
solo tendrás que eliminar (o revocar) esa clave. De esa manera, no afectará a otras
aplicaciones que estén utilizando la misma función.

Este es el inconveniente de las claves de función. Si vas a desarrollar una aplicación


en la que necesites tener varias funciones y cada función la van a utilizar distintas
aplicaciones, tendrás que disponer de muchas claves. Administrar estas claves
y documentarlas sería una pesadilla. En tal caso, puedes optar por las claves de host,
de las que vamos a hablar a continuación.

Configurar una clave de host para todas las


funciones en una sola aplicación de función
Tener diferentes claves para diferentes funciones es un práctica recomendada si
tienes varias funciones que utilizan distintas aplicaciones. Sin embargo, la situación
podría empeorar si hay muchas funciones y muchas aplicaciones cliente que hacen
uso de tus API. La administración de las claves de función en estas aplicaciones
empresariales de gran tamaño con enormes bases de clientes sería realmente tediosa.
Para simplificar todo, puedes segregar todas las funciones relacionadas en una sola
aplicación de función y configurar la autorización para cada aplicación de función
en lugar de hacerlo para cada función individual. Puedes configurar la autorización
para una aplicación de función mediante claves de host.

Estos son los dos tipos diferentes de claves de host disponibles:

• Claves de host normales


• Clave maestra

Crea dos aplicaciones de desencadenador de HTTP, como se muestra en la siguiente


captura de pantalla:

[ 263 ]
Implementar prácticas recomendadas para Azure Functions

Ve a la pestaña Administrar de ambas aplicaciones, como se muestra en las


siguientes capturas de pantalla. Observarás que tanto la clave maestra como las
claves de host son las mismas en las dos aplicaciones:

• Esta es la pestaña de administración de MyApp1:

• Esta es la pestaña de administración de MyApp2:

Al igual que con las claves de función, también puedes crear varias
claves de host si hay varias aplicaciones que utilizan las aplicaciones
de función. Puedes controlar el acceso de diferentes aplicaciones a cada
una de las aplicaciones de función con diferentes teclas.
Puedes crear varias claves de host siguiendo los mismos pasos que para
crear las claves de función normales.

[ 264 ]
Capítulo 9

Y eso no es todo…
Si crees que la clave ha sido atacada, puedes volver a generarla en cualquier
momento a través del botón Renovar. Ten en cuenta que cuando se renueva una
clave, todas las aplicaciones que acceden a la función ya no funcionarán y se
generará un error con el código de estado 401: No autorizado.
Puedes eliminar o revocar la clave si ya no se utiliza en ninguna de las aplicaciones.
A continuación, se muestra una tabla con más información sobre las claves:

Tipo de ¿Cuándo debo ¿Es ¿Es Comentarios


clave usarla? revocable renovable?
(se puede
borrar)?
Clave Si el nivel de No Sí Puedes utilizar una
maestra Autorización clave maestra para
es cualquier función dentro
Administrador de la Function App,
independientemente del
nivel de autorización
configurado.
Clave de Si el nivel de Sí Sí Puedes utilizar la clave
host Autorización de host para todas las
es Función funciones dentro de la
Function App.
Clave de Si el nivel de Sí Sí Puedes utilizar la clave
función Autorización de función solo para una
es Función función determinada.

Microsoft no recomienda compartir la clave maestra, ya que


también la usan las API del runtime. Debes tener gran precaución
con las claves maestras.

Proteger Azure Functions mediante


Azure Active Directory
En la receta anterior, hemos aprendido a habilitar la seguridad en función de las
aplicaciones cliente que acceden a Azure Functions. Sin embargo, si el requisito
es autenticar a los usuarios finales que acceden a las funciones en Azure Active
Directory (AD), Azure Functions proporciona una forma sencilla de configurar este
método conocido como EasyAuth.

[ 265 ]
Implementar prácticas recomendadas para Azure Functions

Gracias a Azure App Service, desde el que se hereda la función EasyAuth, podemos
hacer lo que sea necesario sin escribir una sola línea de código.

Preparación
En esta receta, para simplificar el procedimiento, vamos a utilizar el AD
predeterminado que se crea durante la creación de una cuenta de Azure. Sin
embargo, en los escenarios de producción en tiempo real, ya tendrías un AD
existente que tendría que integrarse. Es recomendable leer este artículo:
https://docs.microsoft.com/azure/active-directory-b2c/active-
directory-b2c-tutorials-web-app.

Cómo hacerlo...
En esta receta, haremos lo siguiente:

• Configurar Azure AD para la Function App


• Registrar la aplicación cliente en Azure AD
• Conceder a la aplicación cliente acceso a la aplicación de back-end
• Probar la funcionalidad de autenticación mediante un token JWT

Configurar Azure AD para la Function App


Sigue estos pasos:

1. Ve a la sección Características de la plataforma de Azure Functions.


2. En la hoja Autenticación/Autorización, realiza los pasos siguientes para
habilitar la autenticación de AD:
1. Haz clic en el botón Activada para habilitar la autenticación.
2. Selecciona la opción Iniciar sesión a través de la opción de menú
Azure Active Directory.
3. Haz clic en el botón Sin configurar para comenzar a configurar
las opciones.

3. El siguiente paso es elegir un registro existente o crear uno nuevo para la


aplicación cliente a la que deseamos conceder acceso. Para ello, pulsa el botón
Rápida del campo Modo de administración. Además, yo opté por crear uno
nuevo e introduje AzureFunctionCookbookV2 como nombre para el registro
de mi aplicación. Haz clic en Aceptar para guardar las configuraciones y se
abrirá la siguiente pantalla.

[ 266 ]
Capítulo 9

4. Obtén el Id. de la aplicación, tal como se muestra. Lo vamos a utilizar


durante nuestra prueba en unos instantes:

Eso es todo. Sin escribir una sola línea de código, hemos terminado con la
configuración de una instancia de Azure AD que funciona como capa de seguridad
y permite el acceso solo a los usuarios autenticados. Es decir, hemos habilitado
OAuth para nuestra Function App de back-end con Azure AD. Vamos a probarlo
rápidamente accediendo a cualquiera de los desencadenadores de HTTP que tienes
en la Function App. Para realizar esta prueba he utilizado Postman. Como es de
esperar, aparecerá un mensaje de error en el que se te pedirá que inicies sesión.

Con las configuraciones actuales, ninguna de las aplicaciones cliente externas podrá
acceder a nuestra API de back-end. Para otorgar el acceso necesario, tienes que
seguir estos pasos:

Registra todas las aplicaciones cliente en Azure AD (para nuestro ejemplo, vamos
a realizar un registro para la aplicación Postman).

Concede acceso a la aplicación de back-end.

Registrar la aplicación cliente en Azure AD


Sigue estos pasos:

1. Abre Azure AD a través del botón Azure Active Directory, tal como se
muestra. Si no aparece en la lista de favoritos, lo puedes buscar en la hoja
Todos los servicios, que también aparece resaltada en la siguiente
captura de pantalla:

[ 267 ]
Implementar prácticas recomendadas para Azure Functions

2. En el menú AD, haz clic en Registros de aplicaciones y, a continuación, haz


clic en el botón de registro Nueva aplicación.
3. Rellena los campos de la siguiente manera y haz clic en el botón Crear para
completar el registro de la aplicación Postman. Dado que nuestra aplicación
cliente es Postman, la URL de inicio de sesión no es importante, por lo que
podemos utilizar http://localhost para nuestro ejemplo:

[ 268 ]
Capítulo 9

4. En unos instantes, se creará la aplicación y se abrirá la siguiente pantalla.


Obtén el Id. de la aplicación y guárdalo en el bloc de notas. Lo vamos
a utilizar en los pasos siguientes. Haz clic en el botón Configuración:

5. En la hoja Configuración, haz clic en el elemento de menú Claves para


generar una clave, que vamos a pasar desde Postman. Para generar la
clave, primero tenemos que proporcionar una Descripción y la Duración
del tiempo de vigencia tras el que debe expirar la clave. Proporciona los
datos como se muestran en la siguiente captura de pantalla y haz clic en el
botón Guardar. La clave real se muestra en el campo de valor solo una vez
inmediatamente después de hacer clic en el botón Guardar, así que asegúrate
de copiarlo y almacenarlo en un lugar seguro. Vamos a utilizarla en breve:

[ 269 ]
Implementar prácticas recomendadas para Azure Functions

Conceder a la aplicación cliente acceso a la


aplicación de back-end
Una vez registrada la aplicación cliente, tenemos que proporcionarle el acceso
a nuestra aplicación de back-end. En esta sección, vamos a aprender a configurarla:
1. Haz clic en la pestaña Permisos necesarios y en el botón Agregar, de
tal forma que se mostrará la hoja Agregar acceso de API, donde debes
seleccionar la API necesaria (en nuestro caso, es la API de back-end
de Azure Functions).
2. En la hoja Agregar acceso de API, haz clic en el botón Seleccionar una API;
inicialmente, se mostrarán las API predeterminadas. Tienes que buscar la
aplicación de back-end con el nombre que hayas proporcionado (en mi caso,
fue AzureFunctionCookBookV2). Selecciona la aplicación de back-end y haz
clic en el botón Seleccionar.
3. El siguiente paso es proporcionar los permisos reales. Haz clic en la hoja
Seleccionar permisos y comprueba el <Backend App name> de acceso
y, a continuación, haz clic en el botón Hecho.
4. Asegúrate de que aparece la siguiente pantalla. También puedes hacer clic en
el botón Conceder permiso para aplicar los cambios:

Probar la funcionalidad de autenticación mediante


un token JWT
Debes tener preparado lo siguiente para probar la funcionalidad mediante Postman:

1. Punto de conexión de token de OAuth 2.0. Para ello, ve a la pestaña Puntos


de conexión de Azure AD y obtén la dirección URL:
°° Tipo de concesión: un valor de client_credentials codificado.
°° Id. de cliente de la aplicación cliente: lo anotaste en el cuarto paso
de la sección Registrar la aplicación cliente en Azure AD.

[ 270 ]
Capítulo 9

°° Clave que generaste para la aplicación cliente: la anotaste en el


quinto paso de la sección Registrar la aplicación cliente en Azure AD.
°° Recurso: recurso al que necesitamos acceder. Es el Id. de cliente de
la aplicación de back-end; lo anotaste en el cuarto paso de la sección
Configurar Azure AD para la Function App.

2. Una vez que dispongas de toda esa información, debes pasar todos los
parámetros y realizar una llamada a un inquilino de Azure AD, que devuelve
el token de portador de la siguiente manera:

3. El siguiente y último paso es realizar una llamada al back-end real


(el desencadenador de HTTP de la Azure Function) pasando el token de
portador de JWT (access_token) que copiamos de la pantalla anterior:

[ 271 ]
Implementar prácticas recomendadas para Azure Functions

4. Como se muestra en esta captura de pantalla, agrega un encabezado de


Autorización y pega el token de JWT. No olvides proporcionar la palabra
portadora de texto.

Configurar la limitación de Azure


Functions mediante API Management
En capítulos anteriores, ya hemos aprendido que podemos utilizar los
desencadenadores de HTTP de Azure Functions como API Web de back-end. Si
deseas restringir el número de solicitudes de las aplicaciones cliente a, por ejemplo,
10 solicitudes por segundo, puede que sea necesario desarrollar gran cantidad de
lógica. Gracias a Azure API Management, no es necesario escribir ninguna lógica
personalizada si integras Azure Functions con API Management.

En esta receta, aprenderemos cómo restringir a los clientes el acceso de API solo una
vez por minuto para una dirección IP determinada. A continuación, se proporcionan
los pasos de alto nivel que seguiremos:

1. Crear un servicio Azure API Management


2. Integrar Azure Functions con API Management
3. Configurar la limitación de solicitudes mediante políticas de entrada
4. Probar la configuración de política de entrada de límite de velocidad

[ 272 ]
Capítulo 9

Preparación
Para empezar, necesitamos crear un servicio Azure API Management mediante los
pasos siguientes:

1. Busca API Management y proporciona todos los detalles siguientes. En el


ejemplo siguiente, he elegido el nivel de precios para Desarrollador. No
obstante, para tus aplicaciones de producción, deberás seleccionar niveles de
precios que no sean para desarrolladores (Básico/Estándar/Premium), ya que
el nivel de Desarrollador (sin SLA) no proporciona ningún SLA. Una vez
que hayas revisado todos los detalles, haz clic en el botón Crear:

[ 273 ]
Implementar prácticas recomendadas para Azure Functions

2. En el momento de redactar la receta, tardó aproximadamente 30 minutos en


crearse una instancia de API Management. Una vez creada, podrás verla en
la hoja de servicios API Management:

Cómo hacerlo...
Con el fin de aprovechar las capacidades API Management, necesitamos integrar
los puntos de conexión de servicio (en nuestro caso, los desencadenadores de HTTP
que hemos creado) con el servicio API Management. En esta sección indicaremos los
pasos necesarios para la integración. Vamos a comenzar integrando los dos.

Integrar Azure Functions con API Management


Sigue estos pasos:

1. Ve a la hoja de API de la Instancia de API Management que has creado


y haz clic en el icono de la Function App.
2. Aparecerá la ventana emergente Crear a partir de Function App, donde
puedes hacer clic en el botón Examinar y se abrirá una barra lateral con el
título Importar Azure Functions, donde se pueden configurar las aplicaciones
de función. Haz clic en el botón Configurar el parámetro obligatorio para
ver todas las aplicaciones de función que contengan desencadenadores de
HTTP. Una vez que hayas seleccionado la Function App, haz clic en el
botón Seleccionar.

[ 274 ]
Capítulo 9

3. El siguiente paso es elegir el desencadenador de HTTP que deseas


integrar con Azure API Management. Después de hacer clic en el botón
Seleccionar, como se ha indicado en el paso anterior, aparecerán todos
los desencadenadores de HTTP asociados con la aplicación de función
seleccionada, como se muestra en la siguiente captura de pantalla. He elegido
un solo desencadenador de HTTP para que resulte más sencillo:

[ 275 ]
Implementar prácticas recomendadas para Azure Functions

4. Una vez realizados todos los pasos anteriores, aparecerá la ventana


emergente Crear a partir de Function App, con un aspecto similar al
siguiente. Cuando hayas revisado todos los datos, haz clic en el botón Crear:

5. Si todo va bien, deberías ver una pantalla como la de la captura


siguiente. Ya hemos terminado con la integración de Azure Functions
con API Management:

[ 276 ]
Capítulo 9

Configurar la limitación de solicitudes mediante


políticas de entrada
Sigue estos pasos:

1. Como se muestra en la captura de pantalla anterior, selecciona la operación


requerida (GET) y haz clic en el enlace del editor de políticas de entrada
(labeled 3), que abrirá el editor de políticas.

API Management nos permite controlar el comportamiento de las API


de back-end (en nuestro caso, los desencadenadores de HTTP) mediante
las políticas de API Management. Puedes controlar las respuestas de
solicitud de entrada y de salida. Puedes obtener más información sobre
este tema en https://docs.microsoft.com/azure/
api-management/api-management-howto-policies.

2. Como tenemos que restringir la tasa de solicitudes dentro de API


Management antes de enviar la solicitud a la Function App de back-end, es
necesario configurar el límite de velocidad en la política de entrada. Crea
una política nueva, tal como se muestra, con un valor de 1 para el atributo
de llamadas y un valor de 60 (en segundos) para el atributo del período de
renovación. Por último, define el valor de counter-key en la dirección IP de la
aplicación cliente:

[ 277 ]
Implementar prácticas recomendadas para Azure Functions

Con esta política de entrada, estaremos indicando a API


Management que restrinja una solicitud por minuto para una
dirección IP determinada.

3. Antes de probar la limitación, nos queda un último paso que consiste en


publicar la API. Para ello, ve a la pestaña Configuración del paso anterior
y asocia la API a un producto publicado (en mi caso, tengo un producto de
inicio predeterminado que ya está publicado). Como se muestra en la captura
de pantalla siguiente, selecciona el producto necesario y haz clic en el
botón Guardar:

Los productos de API Management son un grupo de API al que pueden


suscribirse los desarrolladores de diferentes aplicaciones cliente. Para
obtener más información sobre los productos de API Management,
consulta https://docs.microsoft.com/azure/api-management/
api-management-howto-add-products.

[ 278 ]
Capítulo 9

Probar la configuración de política de entrada de


límite de velocidad
Sigue estos pasos:

1. Ve a la pestaña Prueba y agrega los parámetros o encabezados requeridos


previstos por el desencadenador de HTTP. En mi caso, mi desencadenador
de HTTP requiere un parámetro denominado "name".
2. Ahora, haz clic en el botón Enviar que aparece tras completar el paso anterior
para realizar tu primera solicitud. Debería aparecer algo como lo siguiente
después de obtener una respuesta del back-end:

3. A continuación, haz clic inmediatamente en el botón Enviar. Como se


muestra aquí, debería mostrarse un error, ya que nuestra regla de política
de entrada tan solo permite una solicitud por minuto para una dirección
IP específica:

[ 279 ]
Implementar prácticas recomendadas para Azure Functions

Cómo funciona...
En esta receta, hemos creado una instancia de Azure API Management y hemos
integrado una Azure Function App para aprovechar las funciones de API
Management. Una vez integradas, hemos creado una política de entrada que
restringe a los clientes a realizar una sola llamada por minuto desde una dirección IP
determinada. A continuación, se muestra un diagrama de alto nivel que representa
todo el proceso:

[ 280 ]
Capítulo 9

Acceder de forma segura a SQL


Database desde Azure Functions
mediante Managed Service Identity
En una de nuestras recetas, Interacciones de Azure SQL Database mediante Azure
Functions del capítulo 3, Integración perfecta de Azure Functions con los Servicios de
Azure, hemos aprendido a obtener acceso a una instancia de SQL Database y a sus
objetos desde Azure Functions proporcionando la cadena de conexión (nombre de
usuario y contraseña).

Supongamos que, por cualquier motivo, cambias la contraseña de una cuenta, de


tal manera que las aplicaciones que utilizan la cuenta ya no pueden obtener acceso
a esta. Como desarrollador, ¿no resultaría útil que existiera un recurso en el que
no tuvieras que preocuparte por las credenciales y, en su lugar, la plataforma se
encargase de la autenticación? En esta receta, aprenderemos a obtener acceso a una
instancia de SQL Database desde una función de Azure sin proporcionar un
identificador de usuario ni una contraseña a través de una función denominada
Managed Service Identity.

En el momento de redactar esta receta, el código relacionado con la


recuperación del token de acceso solo estaba disponible con Azure
Functions v1 (.NET Framework), pero no con v2 (.NET Core). Para
cuando estés leyendo este libro, es posible que ya esté disponible la
última versión de .NET Core Framework, por lo que esta receta debería
funcionar también con el runtime de Azure Functions v2.

Preparación
Esta receta nos indica cómo crear Azure Functions (con el runtime v1) y la base de
datos SQL en el mismo grupo de recursos. Si no las has creado, créalas primero
y vuelve luego a esta receta para continuar. Estos son los pasos que vamos a seguir
en esta receta:

1. Crear una aplicación de función con Visual Studio 2017 con el runtime v1
2. Crear un SQL Server lógico y una SQL Database
3. Habilitar Managed Service Identity desde el portal
4. Recuperar información de Managed Service Identity mediante
la CLI de Azure
5. Permitir el acceso de SQL Server a la nueva Managed Service Identity
6. Ejecutar el desencadenador de HTTP y probarlo

[ 281 ]
Implementar prácticas recomendadas para Azure Functions

Cómo hacerlo...
En esta receta, vamos a seguir estos pasos:

1. Crear una aplicación de función con Visual Studio 2017 con el runtime v1
2. Crear un SQL Server lógico y una SQL Database
3. Habilitar la Managed Service Identity

Crear una aplicación de función con Visual Studio


2017 con el runtime v1
Sigue estos pasos:

1. Crea una aplicación de función nueva con el runtime de Azure Functions v1.
2. Una vez creado el desencadenador de HTTP, reemplaza la función por el
código siguiente:
public static class HttpTriggerWithMSI
{
[FunctionName("HttpTriggerWithMSI")]
public static async Task<HttpResponseMessage> Run([HttpTr
igger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a
request.");

string firstname = string.Empty, lastname = string.


Empty, email = string.Empty, devicelist = string.Empty;

dynamic data = await req.Content.


ReadAsAsync<object>();
firstname = data?.firstname;
lastname = data?.lastname;
email = data?.email;
devicelist = data?.devicelist;

SqlConnection con = null;


try
{
string query = "INSERT INTO EmployeeInfo
(firstname,lastname, email, devicelist) " + "VALUES (@firstname,@
lastname, @email, @devicelist) ";

con = new
SqlConnection("Server=tcp:dbserver.database.
windows.net,1433;Initial Catalog=database;Persist Security Info=Fa

[ 282 ]
Capítulo 9

lse;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertifi
cate=False;Connection Timeout=30;");
SqlCommand cmd = new SqlCommand(query, con);

con.AccessToken = (new
AzureServiceTokenProvider()).GetAccessTokenAsync("https://
database.windows.net/").Result;

cmd.Parameters.Add("@firstname", SqlDbType.
VarChar,
50).Value = firstname;
cmd.Parameters.Add("@lastname", SqlDbType.VarChar,
50)
.Value = lastname;
cmd.Parameters.Add("@email", SqlDbType.VarChar,
50)
.Value = email;
cmd.Parameters.Add("@devicelist", SqlDbType.
VarChar)
.Value = devicelist;
con.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (con != null)
{
con.Close();
}
}
return req.CreateResponse(HttpStatusCode.OK, "Hello,
Successfully inserted the data");
}

El código anterior es el código que copié del capítulo 3, Integración perfecta de Azure
Functions con los Servicios de Azure, con los cambios siguientes, pero la cadena de
conexión no contiene el Id. de usuario ni la contraseña.

1. Agrega una nueva línea de código para recuperar el token de acceso:


con.AccessToken = (new AzureServiceTokenProvider()).
GetAccessTokenAsync("https://database.windows.net/").Result;

2. Agrega los siguientes paquetes NuGet a la Function App:


Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
Install-Package Microsoft.Azure.Services.AppAuthentication

[ 283 ]
Implementar prácticas recomendadas para Azure Functions

3. Asegúrate de que no hay errores de compilación y, a continuación, publica


la Function App en Azure. Este paso garantiza que la aplicación de función
se cree con el runtime v1. Haz clic en el botón Publicar, que abre la ventana
emergente siguiente:

4. A continuación, proporciona el Grupo de recursos y demás datos, como se


muestra en la siguiente captura de pantalla, y haz clic en el botón Crear:

[ 284 ]
Capítulo 9

Crear un SQL Server lógico y una SQL Database


Crea un SQL Server y una base de datos de SQL en el mismo grupo de recursos en
el que hayas creado la Azure Function App. En mi caso, mi nombre de grupo de
recursos es AzureServerlessCookbookv1.

Habilitar la Managed Service Identity


Sigue estos pasos:

1. Ve a las características de la Plataforma de la Function App y haz clic en


Managed Service Identity.
2. En la pestaña Managed Service Identity, haz clic en Activada y en Guardar,
como se muestra a continuación:

Recuperar información de Managed Service Identity


Sigue estos pasos:

1. Autentica la identidad de tu cuenta de Azure mediante la CLI de Azure.


Para ello, ejecuta el comando az login en el símbolo del sistema, como se
muestra en la siguiente captura de pantalla:

2. Se te pedirá que proporciones las credenciales de tu cuenta de Azure


para iniciar sesión en Azure Portal. Una vez que hayas proporcionado tus
credenciales, mostrará las suscripciones disponibles en la consola
de comandos.

[ 285 ]
Implementar prácticas recomendadas para Azure Functions

3. Ahora vamos a recuperar los datos de la entidad de servicio ejecutando el


siguiente comando:
az resource show --name <<Function App Name>> --resource-group
<<Resource Group>> --resource-type Microsoft.Web/sites --query
identity

4. Si has configurado la identidad administrada correctamente, aparecerá algo


similar a lo siguiente como salida del comando anterior:

5. Anota el valor de PrincipalID, que se recupera en el paso anterior. Lo


vamos a utilizar en la sección siguiente.

Permitir el acceso de SQL Server a la nueva Managed


Service Identity
En esta sección, vamos a crear un usuario administrador que tenga acceso al SQL
Server que hemos creado anteriormente:

1. Ejecuta el siguiente comando en el símbolo del sistema pasando el valor de


PrincipalID que anotaste en la sección anterior:
az sql server ad-admin create --resource-group
AzureServerlessCookbookv1 --server-name azuresqlmsidbserver
--display-name sqladminuser --object-id <Principe Id>

2. Al ejecutar el comando anterior, se crea un nuevo usuario administrador en


la base de datos maestra de SQL Server.
3. Crea una tabla denominada EmployeeInfo utilizando el siguiente script:
CREATE TABLE [dbo].[EmployeeInfo]( [PKEmployeeId] [bigint]
IDENTITY(1,1) NOT NULL, [firstname] [varchar](50) NOT NULL,
[lastname] [varchar](50) NULL, [email] [varchar](50) NOT NULL,
[devicelist] [varchar](max) NULL, CONSTRAINT [PK_EmployeeInfo]
PRIMARY KEY CLUSTERED ( [PKEmployeeId] ASC ) )

[ 286 ]
Capítulo 9

Ejecutar el desencadenador de HTTP y probarlo


Sigue estos pasos:

1. Abre Postman y envía una solicitud, tal como se muestra:

2. Ahora revisemos la SQL Database para comprobar si se ha insertado


el registro:

[ 287 ]
Implementar prácticas recomendadas para Azure Functions

Y eso no es todo…
Asegúrate de que la clase tiene todos los espacios de nombres siguientes:
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using System.Data.SqlClient;
using System.Data;
using System;
using Microsoft.Azure.Services.AppAuthentication;

Consulta también
Consulta la receta Interacciones de Azure SQL Database mediante Azure Functions del
capítulo 3, Integración perfecta de Azure Functions con los Servicios de Azure.

Código compartido en Azure Functions


mediante bibliotecas de clases
Has aprendido a reutilizar un método auxiliar en una aplicación de función de
Azure. Sin embargo, no se puede reutilizar en otras aplicaciones de función ni en
ningún otro tipo de aplicación, como una aplicación web o una aplicación WPF. En
esta receta, vamos a desarrollar y crear un archivo .dll nuevo y aprenderás a usar las
clases y sus métodos en Azure Functions.

[ 288 ]
Capítulo 9

Cómo hacerlo...
Sigue estos pasos:

1. Crea una aplicación de Biblioteca de clases nueva mediante Visual Studio.


Yo he utilizado Visual Studio 2017:

2. Crea una clase nueva denominada Helper y pega el código siguiente en el


archivo de clase nuevo:
namespace Utilities
{
public class Helper
{
public static string GetReusableFunctionOutput()
{
return "This is an output from a Resuable Library
across functions";
}
}
}

3. Cambia la configuración de compilación a Lanzamiento y compila la


aplicación para crear el archivo .dll que se utilizará en Azure Functions.
4. Abre el Editor de App Service de la Function App a través del
botón Editor de App Service, que está disponible en Características
de la plataforma.
[ 289 ]
Implementar prácticas recomendadas para Azure Functions

5. A continuación, crea una nueva carpeta bin. Para ello, haz clic con el botón
derecho en el área vacía debajo de los archivos ubicados en WWWROOT.
6. Después de hacer clic en el elemento Nueva carpeta de la pantalla resultante,
aparecerá un cuadro de texto nuevo en el que debes especificar el
nombre "bin".
7. A continuación, haz clic con el botón derecho en la carpeta bin y selecciona la
opción Cargar archivos para cargar el archivo .dll que hemos creado en
Visual Studio.
8. Esto es lo que se muestra después de cargar el archivo .dll en la carpeta bin:

9. Ve a la Azure Function donde deseas utilizar el método compartido. Con


fines de demostración, he creado dos Azure Functions (un desencadenador
de HTTP y un desencadenador de temporizador):

[ 290 ]
Capítulo 9

10. A continuación, iremos a la función ReusableMethodCaller1 y realizaremos


los siguientes cambios:
°° Agrega una nueva política #r, como se indica a continuación, al
método run.csx de la Azure Function ReusableMethodCaller1.
Observa que, en este caso, se requiere .dll:
#r "../bin/Utilities.dll"

°° Agrega un espacio de nombres nuevo, como se muestra


a continuación:
using Utilities;

11. Ahora ya estamos listos para utilizar el método compartido


GetReusableFunctionOutput en nuestra Azure Function. A continuación,
reemplaza el desencadenador de HTTP con lo siguiente:
log.LogInformation(Helper.GetReusableFunctionOutput());

12. Al ejecutar la aplicación, deberías ver el siguiente mensaje en los registros:

13. Repite los mismos pasos para agregar la referencia y el espacio de nombres
de la biblioteca de utilidades, también en la segunda Azure Function,
ReusableMethodCaller2. Si has realizado los cambios correctamente,
debería mostrarse algo muy parecido a lo siguiente:

Cómo funciona...
Hemos creado un archivo .dll que contiene el código reutilizable que se puede
utilizar en cualquiera de las Azure Functions que requieren la funcionalidad
disponible a través del archivo .dll.
Con el archivo .dll ya listo, hemos creado una carpeta bin en la Function App
y hemos agregado el archivo .dll a la carpeta bin.

[ 291 ]
Implementar prácticas recomendadas para Azure Functions

Ten en cuenta que hemos agregado la carpeta bin al directorio


WWWROOT para que esté disponible para todas las Azure
Functions disponibles en la aplicación de función.

Y eso no es todo…
Si deseas utilizar el código compartido únicamente en una función, debes
agregar la carpeta bin junto con el archivo .dll en la carpeta de la Azure
Function correspondiente.

Otra ventaja importante del uso de bibliotecas de clases es que mejora el


rendimiento, dado que ya están compiladas y listas para su ejecución.

Usar clases fuertemente tipadas en


Azure Functions
En los capítulos iniciales, hemos desarrollado un desencadenador de HTTP
denominado RegisterUser que actúa como una API web y puede consumirlo
cualquier aplicación capaz de realizar solicitudes HTTP. Sin embargo, puede haber
otros requisitos en situaciones en las que existan varias aplicaciones que creen
mensajes en una cola con los datos necesarios para crear un usuario. Para simplificar
la tarea, vamos a utilizar el explorador de Azure Storage para crear un mensaje
de la cola.

En esta receta, vamos a aprender a obtener los datos del usuario de la cola mediante
objetos fuertemente tipados.

Preparación
Antes de seguir avanzando, vamos a seguir estos pasos:

1. Crea una cuenta de Azure Storage (yo he creado azurefunctionscookbook)


en tu suscripción de Azure.
2. Instala el explorador de Microsoft Azure Storage si aún no las instalado.
3. Una vez creado el explorador de Azure Storage, conéctate a la cuenta de
Azure Storage.

[ 292 ]
Capítulo 9

Cómo hacerlo...
Sigue estos pasos:
1. Utiliza el explorador de Azure Storage para crear una cola denominada
registeruserqueue en la cuenta de Azure Storage denominada
azurefunctionscookbook. Se presupone que todas las demás aplicaciones
estarían creando mensajes en la cola registeruserqueue.
2. Ve a Azure Functions y crea una Azure Function nueva mediante el
desencadenador de Azure Queue Storage y, a continuación, selecciona la cola
que hemos creado.
3. Es posible que se te pida que instales las extensiones de Azure Storage si
no están ya instaladas. Una vez instaladas las extensiones, proporciona los
datos de la cola y haz clic en el botón Crear, como se muestra en la siguiente
captura de pantalla:

4. Una vez creada la función, reemplaza el código predeterminado con el


siguiente código. Siempre que se crea un mensaje de cola, el mensaje JSON
se deserializa automáticamente y se rellena en un objeto denominado
myQueueItem. En el siguiente código, solo vamos a imprimir los valores de
los objetos de la ventana Registros:
using System;
public static void Run(User myQueueItem, ILogger log)
{

[ 293 ]
Implementar prácticas recomendadas para Azure Functions

log.LogInformation($"A Message has been created for a new


User");
log.LogInformation($"First name: {myQueueItem.firstname}" );
log.LogInformation($"Last name: {myQueueItem.lastname}" );
log.LogInformation($"email: {myQueueItem.email}" );
log.LogInformation($"Profile Url: {myQueueItem.ProfilePicUrl}"
);
}
public class User
{
public string firstname { get;set;}
public string lastname { get;set;}
public string email { get;set;}
public string ProfilePicUrl { get;set;}
}

5. Ve al explorador de Azure Storage y crea un nuevo mensaje en


registeruserqueue, como se muestra en la siguiente captura de pantalla:

[ 294 ]
Capítulo 9

6. Haz clic en Aceptar para crear el mensaje de cola, vuelve a la Azure Function
y revisa los registros, como se muestra en la siguiente captura de pantalla:

Cómo funciona...
Hemos desarrollado una nueva función de cola que se activa cuando se agrega un
nuevo mensaje a la cola. Hemos creado un nuevo mensaje de la cola con todos los
datos necesarios para crear el usuario. Puedes seguir reutilizando el código de la
Azure Function para pasar el objeto de usuario (en este caso, myQueueItem) a la clase
de capa de base de datos, que se encarga de insertar los datos en una base de datos
o en cualquier otro medio persistente.

Y eso no es todo…
En esta receta, el tipo del parámetro de mensaje de cola aceptado por el método Run
ha sido User. El runtime de Azure Functions se encargará de deserializar el mensaje
JSON disponible en la cola para el tipo personalizado; en nuestro caso, es "user".

[ 295 ]
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).

[ 296 ]
Capítulo 10

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:

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.
[ 297 ]
Configurar aplicaciones sin servidor en el entorno de producción

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:

2. Crea una aplicación de función vacía utilizando el portal de administración


de Azure:

3. Una cuenta de almacenamiento: cargaremos el archivo de paquete en la


cuenta de almacenamiento.
[ 298 ]
Capítulo 10

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.
2. 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:

3. Crea un contenedor de blob (con acceso privado) y carga el archivo


de paquete desde el portal o mediante el explorador de Azure Storage.
4. 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-shared-
access-signature-part-1:

5. 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:

[ 299 ]
Configurar aplicaciones sin servidor en el entorno de producción

6. 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:

[ 300 ]
Capítulo 10

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:

[ 301 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. 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):

3. Busca la palabra function y haz clic en la plantilla 101-function-app-create-


dynamic para crear la aplicación Azure Function con el plan de consumo:

[ 302 ]
Capítulo 10

4. 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.
5. 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:

6. 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:

[ 303 ]
Configurar aplicaciones sin servidor en el entorno de producción

7. 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.

[ 304 ]
Capítulo 10

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:

[ 305 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. 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:

[ 306 ]
Capítulo 10

3. 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:

[ 307 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. 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:

[ 308 ]
Capítulo 10

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:
[ 309 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. 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");
}
}
[ 310 ]
Capítulo 10

3. Publica el proyecto en Azure haciendo clic con el botón derecho en


el proyecto y en Publicar en el menú.
4. Agrega la clave de configuración y la cadena de conexión en la hoja
Configuración de la aplicación:

5. Ejecuta la función haciendo clic en el botón Ejecutar, que registra los


resultados en la ventana de resultados:

[ 311 ]
Configurar aplicaciones sin servidor en el entorno de producción

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:

2. 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:

3. 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

[ 312 ]
Capítulo 10

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:

[ 313 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. 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:

3. 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:

[ 314 ]
Capítulo 10

4. 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:

5. 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.
6. 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.
7. La interfaz de usuario de Swagger tendrá el aspecto siguiente con los
mensajes adecuados junto con los formatos de solicitud y respuesta:

[ 315 ]
Configurar aplicaciones sin servidor en el entorno de producción

8. 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:

[ 316 ]
Capítulo 10

9. 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:

[ 317 ]
Configurar aplicaciones sin servidor en el entorno de producción

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

[ 318 ]
Capítulo 10

Crear microservicios
Sigue estos pasos:

1. Crea tres aplicaciones de función para cada uno de los microservicios


que hemos planificado:

2. 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
Mensaje de salida
desencadenador de HTTP
Hola, <<Nombre>>: bienvenido/a al
Men-HttpTrigger
microservicio Hombres
Hola, <<Nombre>>: bienvenido/a al
Women-HttpTrigger
microservicio Mujeres
Hola, <<Nombre>>: bienvenido/a al
Kids-HttpTrigger
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:

[ 319 ]
Configurar aplicaciones sin servidor en el entorno de producción

2. Serás redirigido a la hoja de detalles:

[ 320 ]
Capítulo 10

3. 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 Plantilla Dirección URL de back-end (las direcciones URL de los


proxy de ruta desencadenadores de HTTP creados en el paso anterior)
Hombres /Hombres https://azurefunctioncookbook-men.
azurewebsites.net/api/Men-HttpTrigger
Mujeres /Mujeres https://azurefunctioncookbook-women.
azurewebsites.netapi/Women-HttpTrigger
Niños /Niños https://azurefunctioncookbook-kids.
azurewebsites.netapi/Kids-HttpTrigger

4. Después de crear los tres proxies, la lista deberá tener el aspecto siguiente:

5. En la captura de pantalla anterior, puedes ver tres dominios diferentes.


Sin embargo, si deseas compartirlos con las aplicaciones cliente, no es
necesario que compartas estas direcciones URL. Todo lo que debes hacer
es compartir la dirección URL de los proxies que puedes ver en la pestaña
Proxy. Aquí se encuentran las direcciones URL de los tres proxies que
hemos creado:

• https://azurefunctioncookbook-gateway.azurewebsites.net/Men
• https://azurefunctioncookbook-gateway.azurewebsites.net/Women
• https://azurefunctioncookbook-gateway.azurewebsites.net/Kids

[ 321 ]
Configurar aplicaciones sin servidor en el entorno de producción

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.

[ 322 ]
Capítulo 10

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.

[ 323 ]
Configurar aplicaciones sin servidor en el entorno de producción

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)
2. Crea algunos ajustes de la aplicación:

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.

[ 324 ]
Capítulo 10

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:

2. Se abrirá el Explorador de recursos, desde donde puedes desplazarte


por todos los elementos internos de un servicio determinado:

[ 325 ]
Configurar aplicaciones sin servidor en el entorno de producción

3. Haz clic en el elemento config, como se muestra en la captura de pantalla


anterior, que abre todos los elementos relacionados con las configuraciones:

4. 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.

[ 326 ]
Capítulo 10

5. 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:

6. 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.

[ 327 ]
Configurar aplicaciones sin servidor en el entorno de producción

7. 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.

[ 328 ]
Implementar la integración
continua mediante Azure
DevOps
En este capítulo, vas a aprender lo siguiente:

• Integración continua: crear una definición de compilación


• Integración continua: poner en cola una compilación y desencadenarla
manualmente
• Configurar y desencadenar una compilación automatizada
• Integración continua: ejecutar casos de pruebas unitarias en la canalización
• Crear una definición de versión
• Desencadenar la versión automáticamente

Introducción
Como profesional de software, es posible que ya conozcas las distintas metodologías
de desarrollo de software que se utilizan. Con independencia de la metodología,
habrá distintos entornos (por ejemplo, desarrollo, ensayo y producción), en los que
el ciclo de vida de la aplicación debe preceder a estas fases críticas relacionadas con
el desarrollo:

1. Desarrollar en base a los requisitos


2. Compilar la aplicación y corregir los errores
3. Implementar/publicar el paquete en un entorno (desarrollo/ensayo/
producción)

[ 330 ]
Capítulo 11

4. Probar según los requisitos


5. Promover el paso al siguiente entorno (de desarrollo a ensayo y de ensayo
a producción)

Ten en cuenta que, para facilitar la tarea, las fases iniciales, como la
recopilación de requisitos, la planificación, el diseño y la arquitectura, se
han excluido. De esta forma, se da mayor énfasis a las fases relevantes
para este capítulo.

Para cada cambio que debas aplicar al software, es necesario compilar e implementar
la aplicación en distintos entornos. Puede darse el caso de que distintos equipos
sean responsables de publicar las compilaciones en entornos diferentes. Dado
que intervienen distintos entornos y equipos, el cálculo de la cantidad de tiempo
necesario para ejecutar las compilaciones e implementarlas en entornos diferentes
dependería más de los procesos que utilicen los equipos.

Con el fin de agilizar y automatizar los pasos mencionados anteriormente, en este


capítulo analizaremos algunas de las técnicas populares del sector para publicar el
software rápidamente y con una infraestructura mínima.

En los capítulos anteriores, la mayoría de las recetas nos han


proporcionado una solución para un problema empresarial concreto.
Sin embargo, en este capítulo intentaremos proporcionar una
solución para la integración y la entrega continuas de la aplicación
fundamental para el negocio.

El equipo de Azure DevOps añade continuamente nuevas funciones a Azure


DevOps en https://dev.azure.com (anteriormente denominado VSTS en
https://www.visualstudio.com) y actualiza la interfaz de usuario. Es posible
que las capturas de pantalla que se muestran en este capítulo no coincidan con las
pantallas de https://dev.azure.com cuando leas esto.

Requisitos previos
Si no lo has hecho previamente, crea lo siguiente:

1. Crea la organización de Azure DevOps que quieras en https://dev.azure.


com y un nuevo proyecto en la cuenta. Al crear el proyecto, puedes elegir Git
o Control de versiones de Team Foundation como repositorio con control de
versiones. He utilizado Control de versiones de Team Foundation para mi
proyecto:

[ 331 ]
Implementar la integración continua mediante Azure DevOps

2. Configura el proyecto de Visual Studio que has desarrollado en el capítulo 4,


Comprender la experiencia de desarrollador integrada de Visual Studio Tools para
Azure Functions, en Azure DevOps. Puedes consultar el enlace https://www.
visualstudio.com/en-us/docs/setup-admin/team-services/set-up-vs para
seguir el procedimiento paso a paso de creación de una cuenta y un proyecto
nuevos mediante Azure DevOps.

Voy a aplicar pequeños cambios a los mensajes de respuesta


integrados en el código para que muestren distinta información.
Asegúrate de modificar las pruebas unitarias en consecuencia. De lo
contrario, se producirá un error en la compilación.

Integración continua: crear una


definición de compilación
La definición de compilación es un conjunto de tareas necesarias para configurar una
compilación automatizada del software. En esta receta, seguiremos estos pasos:

• Crear la plantilla de definición de compilación


• Proporcionar toda la información de entrada necesaria para los distintos
pasos de creación de la definición de compilación

[ 332 ]
Capítulo 11

Preparación
Establece los siguientes requisitos previos:

1. Crear una cuenta de Azure DevOps.


2. Para crear un proyecto, selecciona Control de versiones de Team
Foundation, tal como se muestra en la siguiente captura de pantalla:

[ 333 ]
Implementar la integración continua mediante Azure DevOps

Cómo hacerlo...
Sigue estos pasos:

1. Ve a la pestaña Canalizaciones de la cuenta de Azure DevOps, haz clic


en Versiones y selecciona Nueva canalización para iniciar el proceso de
creación de una nueva definición de compilación, tal como se muestra en la
siguiente captura de pantalla:

2. En el próximo paso, haz clic en el enlace de uso del diseñador visual, tal
como se muestra en la siguiente captura de pantalla:

[ 334 ]
Capítulo 11

3. Accederás a la pantalla Seleccione el repositorio en la que podrás seleccionar


el repositorio. Para este ejemplo, he obtenido el código en TFVC. Como se
muestra a continuación, selecciona TFVC y haz clic en Continuar. Asegúrate
de elegir tu proyecto. En mi caso, AzureServerlessCookBook:

4. Llegarás al paso Seleccionar una plantilla, en el que podrás seleccionar


la plantilla necesaria para tu aplicación. Para esta receta seleccionaremos
Función de C#, tal como se muestra en la siguiente captura de pantalla. Haz
clic en el botón Aplicar:

[ 335 ]
Implementar la integración continua mediante Azure DevOps

5. El paso de creación de compilación consta de un conjunto de pasos


que se utilizan para definir la plantilla de compilación. Cada paso tiene
determinados atributos que debemos revisar y proporcionar información
de entrada para todos los campos necesarios en base a nuestros requisitos.
Para empezar, vamos a proporcionar un nombre significativo en el paso de la
canalización y a garantizar la selección de Hosted VS2017 en el desplegable
Grupo de agentes, tal como se muestra en la siguiente captura de pantalla:

Un agente es un software hospedado en el cloud capaz de


ejecutar una compilación. Como nuestro proyecto se basa
en VS2017, hemos elegido Hosted VS2017.

[ 336 ]
Capítulo 11

6. En el paso Obtener orígenes, asegúrate de seleccionar lo siguiente:


1. Selecciona el sistema de control de versiones que desees.
2. Elige el repositorio que desees compilar. En mi ejemplo, he elegido
AzureServerlessCookBook:

7. Deja las opciones predeterminadas en los siguientes pasos:


°° Usar NuGet y Restaurar NuGet: este espacio es necesario para
descargar e instalar todos los paquetes que requiere la aplicación.
°° Compilar solución: este paso utiliza la compilación de MS y tiene
todos los comandos predefinidos para crear la compilación.
°° Ensamblados de prueba: resultaría muy útil si tuviésemos pruebas
automatizadas. Vamos a aplicar cambios a este paso en la receta
Integración continua: ejecutar casos de pruebas unitarias en la canalización
más adelante en este capítulo.
°° Archivos de almacenamiento: este paso nos permite archivar las
carpetas en el formato necesario
°° Ruta de publicación de símbolos: estos símbolos resultan útiles si
quieres depurar la aplicación hospedada en el agente de VM.
°° Publicar artefacto: en este paso se relaciona la configuración con
los artefactos y la ruta de almacenamiento del artefacto (paquete de
compilación).

8. Cuando revises todos los valores de todos los campos, haz clic en Guardar,
tal como se muestra en la siguiente captura de pantalla. Vuelve a hacer clic
en Guardar en el cuadro emergente Guardar definición de compilación:

[ 337 ]
Implementar la integración continua mediante Azure DevOps

Cómo funciona...
La definición de compilación es un esquema de las tareas necesarias para
compilar una aplicación de software. En esta receta, hemos utilizado una plantilla
predeterminada para crear la definición de compilación. También podemos elegir
una plantilla en blanco y crear la definición mediante la selección de las tareas
disponibles en Azure DevOps.

Cuando ejecutes la definición de compilación (de forma manual o automática, lo que


se explicará en las recetas posteriores), las distintas tareas se ejecutarán en el orden
en el que las hayas configurado. También puedes reorganizar los pasos: arrástralos
y suéltalos en la sección de la canalización.

El proceso de compilación comienza con la obtención del código fuente del


repositorio elegido y la descarga de los paquetes NuGet necesarios y, a continuación,
inicia el proceso de compilación del paquete. Cuando el proceso se haya completado,
creará un paquete y lo almacenará en una carpeta configurada para el directorio
build.artifactstagingdirectory (consulta el campo Ruta de acceso para
publicar de la tarea Publicar artefacto).

Obtén más información sobre los distintos tipos de variables de la pestaña Variables
que se muestran aquí:

[ 338 ]
Capítulo 11

Y eso no es todo…
• Azure DevOps proporciona muchas tareas. Para elegir una nueva tarea para
la plantilla, haz clic en el botón Agregar tarea (+), tal como se muestra en la
siguiente captura de pantalla:

• Si no encuentras una tarea que se ajuste a tus requisitos, busca la adecuada


en el Marketplace. Para ello, haz clic en el botón Marketplace que aparece en
la captura de pantalla previa.
• La función C# tiene el conjunto adecuado de tareas necesarias para
configurar la definición de compilación para Azure Functions.

Integración continua: poner en cola


una compilación y desencadenarla
manualmente
En la receta anterior has aprendido a crear y configurar la definición de compilación.
En esta aprenderás a desencadenar la compilación manualmente y comprenderás el
proceso de compilación de la aplicación.

Preparación
Antes de comenzar, asegúrate de lo siguiente:

• Has configurado la definición de compilación tal como se mencionaba en la


receta anterior.
• Todo el código fuente se ha registrado en el proyecto de Azure DevOps.

[ 339 ]
Implementar la integración continua mediante Azure DevOps

Cómo hacerlo...
Sigue estos pasos:

1. Dirígete a la definición de compilación denominada


AzureServerlessCookBook-C# Function-CI y haz clic en el botón Cola
disponible en el lado derecho, tal como se muestra en la siguiente captura de
pantalla:

2. En el cuadro emergente Compilación en cola para


AzureServerlessCookBook-C# Function-CI, asegúrate de seleccionar la
opción Hosted VS2017 en el desplegable Grupo de agentes si utilizas Visual
Studio 2017 y haz clic en el botón Cola, tal como se muestra en la siguiente
captura de pantalla:

[ 340 ]
Capítulo 11

3. En unos minutos, la compilación se pondrá en la cola y aparecerá el mensaje,


tal como se muestra en la siguiente captura de pantalla:

4. Al hacer clic en Id. de compilación (en nuestro caso, 20181025.1) comenzará


el proceso. Esperará unos segundos a que un agente disponible lo inicie.
5. Después de unos instantes, se iniciará el proceso de compilación. Poco
después, la compilación se completará y podrás revisar los pasos de la
compilación en los registros, tal como se muestra a continuación. Por ahora,
haz caso omiso de la advertencia que aparece en Ensamblados de prueba.
Resolveremos este problema en la receta Integración continua: ejecutar casos
de pruebas unitarias en la canalización más adelante en este capítulo:

[ 341 ]
Implementar la integración continua mediante Azure DevOps

6. Si deseas ver el resultado de la compilación, haz clic en el botón Artefactos


destacado en la siguiente captura de pantalla. Para descargar los archivos,
haz clic en el botón Descargar que se muestra a continuación:

Configurar y desencadenar una


compilación automatizada
Para la mayoría de las aplicaciones, es posible que no tenga sentido realizar
compilaciones manuales en Azure DevOps. Lo tendría si pudiésemos configurar la
integración continua (CI) mediante la automatización del proceso de activación de
la compilación para cada inserción/confirmación de los desarrolladores.

En esta receta, aprenderás a configurar la integración en Azure DevOps para el


proyecto del equipo. Además, descubrirás cómo desencadenar la compilación
automatizada mediante la aplicación de cambios al código de la función de Azure
de desencadenador de HTTP que hemos creado en el capítulo 4, Comprender la
experiencia de desarrollador integrada de Visual Studio Tools para Azure Functions.

[ 342 ]
Capítulo 11

Cómo hacerlo...
Sigue estos pasos:

1. Dirígete a la definición de compilación AzureServerlessCookBook-C#


Function-CI. Para ello, haz clic en el botón Editar, tal como se muestra en la
siguiente captura de pantalla:

2. En la definición de compilación, haz clic en el menú Desencadenadores que


se muestra a continuación:

3. Ahora, haz clic en la casilla de verificación Habilitar la integración continua


para activar el desencadenador de compilación automatizado.
4. Para guardar los cambios, haz clic en la flecha junto al botón Guardar y cola
y en el botón Guardar disponible en el menú desplegable, que se muestra en
la siguiente captura de pantalla:

[ 343 ]
Implementar la integración continua mediante Azure DevOps

5. Vamos a dirigirnos al proyecto de función de Azure en Visual Studio. Aplica


un pequeño cambio a la última línea del código fuente de la función Run que
se muestra a continuación. He sustituido la palabra hola por Prueba de
desencadenador de compilación automatizada:
return name != null ? (ActionResult)new OkObjectResult($"Automated
Build Trigger test by, { name}")
: new BadRequestObjectResult("Please pass a name on the
query string or in the request body");

6. Vamos a registrar el código y a confirmar los cambios en el control de código


fuente. Tal como se muestra aquí, se generará un nuevo Id. de conjunto de
cambios. En este caso, es Changeset 32:

7. De forma inmediata, regresa a la definición de compilación de Azure DevOps


para comprobar que se ha desencadenado automáticamente una nueva
compilación y que está en curso, tal como se muestra en la siguiente captura
de pantalla:

[ 344 ]
Capítulo 11

Cómo funciona...
A continuación, se indican los pasos que hemos seguido en esta receta:

1. Hemos activado el desencadenador de compilación automático para la


definición de compilación.
2. Hemos aplicado un cambio al código base y lo hemos registrado en TFVC.
3. De forma automática, se ha desencadenado una nueva compilación en Azure
DevOps (se compila inmediatamente después de confirmar el código en
TFVC).

Y eso no es todo…
Si quieres que los desarrolladores solo inserten el código después de una
compilación correcta, habilita la inserción en el repositorio validada. Para ello, edita
la definición de compilación, dirígete a la pestaña Desencadenadores y a la opción
Habilitar la inserción en el repositorio validada, tal como se muestra en la siguiente
captura de pantalla:

Regresa a Visual Studio y aplica algunos cambios al código. Si intentas insertar el


código sin compilar la aplicación en Visual Studio, aparecerá una alerta, tal como se
muestra a continuación:

[ 345 ]
Implementar la integración continua mediante Azure DevOps

Haz clic en Cambios de compilación en el paso anterior para iniciar la compilación


en Visual Studio. En cuanto se complete la compilación en Visual Studio, el código
se insertará en Azure DevOps y, a continuación, se desencadenará automáticamente
una nueva compilación, tal como se muestra a continuación:

Integración continua: ejecutar casos de


pruebas unitarias en la canalización
Uno de los pasos más importantes de cualquier metodología de desarrollo de
software es escribir pruebas unitarias automatizadas que validen la precisión de
nuestro código. También es importante que realicemos estas pruebas unitarias cada
vez que el desarrollador publique código nuevo, para proporcionar cobertura de
código de prueba.

En esta receta, aprenderemos a incorporar el proceso de compilación de las pruebas


unitarias que hemos desarrollado en la receta Desarrollar pruebas unitarias para los
desencadenadores de HTTP de Azure Functions del capítulo 6, Explorar las herramientas de
pruebas para la validación de Azure Functions.

[ 346 ]
Capítulo 11

Cómo hacerlo
Sigue estos pasos:

1. En la receta Integración continua: crear una definición de compilación de este


capítulo, hemos utilizado una plantilla de compilación que tenía los pasos
Compilar solución y Ensamblados de prueba de la compilación, tal como se
muestra en la siguiente captura de pantalla:

2. Haz clic en Ensamblados de prueba, tal como se muestra en la captura de


pantalla anterior. Sustituye la configuración predeterminada por la que se
proporciona aquí en el campo Archivos de prueba:
**\$(BuildConfiguration)\**\*test*.dll
!**\obj\**
!**\*TestAdapter.dll

3. Los ajustes anteriores permiten al Ejecutor de pruebas hacer lo siguiente:


°° Buscar los archivos .dll con la palabra Test en el nombre de la
carpeta de release en cualquier ubicación de los artefactos. Quizá te
preguntes de dónde ha salido la carpeta release. Se trata del valor
de la variable $(BuildConfiguration) de la sección Variables que
se muestra en la siguiente captura de pantalla:

[ 347 ]
Implementar la integración continua mediante Azure DevOps

°° Haz caso omiso de todos los archivos .dll de la carpeta obj, ya que
nuestro objetivo es trabajar solo en los archivos .dll ubicados en la
carpeta release.
4. Eso es todo. Ahora vamos a poner la compilación en cola. Para ello, haremos
clic en el botón Cola después de guardar los cambios. Transcurridos unos
minutos, la canalización de compilación se superará sin advertencias, tal
como se muestra en la siguiente captura de pantalla:

[ 348 ]
Capítulo 11

5. A continuación, se muestra el resumen de los casos de prueba. Puedes ver


el gráfico que muestra el porcentaje de casos de prueba que se han superado
y los que han fallado:

Y eso no es todo…
Si has respetado las convenciones de nomenclatura que se indican en las
instrucciones, no tendrás problemas con la receta. Sin embargo, si has utilizado un
nombre diferente para el proyecto unitario y no has incluido la palabra test en
el nombre del proyecto (el mismo nombre del archivo .dll generado), cambia el
formato en el siguiente ajuste:
**\$(BuildConfiguration)\**\*whateverwordyouhaveinthenameofthedllfi
le*.dll

En la receta has utilizado *, ** y !, que se denominan patrones de coincidencia


de archivos. Puedes obtener más información sobre los patrones de coincidencia
de archivos en https://docs.microsoft.com/en-us/azure/devops/pipelines/
tasks/file-matching-patterns?view=vsts.

Crear una definición de versión


Ya sabemos cómo crear una definición de compilación y desencadenar una
compilación automatizada en las canalizaciones de Azure DevOps. El siguiente paso
es publicar o implementar el paquete en un entorno en el que los que participan en el
proyecto puedan revisarlo y proporcionar comentarios. Para ello, primero tenemos
que crear una definición de versión de la misma forma que creamos las definiciones
de las compilaciones.

[ 349 ]
Implementar la integración continua mediante Azure DevOps

Preparación
He utilizado el nuevo editor de definiciones de versión para visualizar las
canalizaciones de implementación. El editor de definiciones de versión aún está en
estado preview. Al leer este documento, si sigue en versión preview, actívalo. Para
ello, haz clic en la imagen de perfil y, a continuación, en el enlace Características
de versión preview, tal como se muestra en la siguiente captura de pantalla:

A continuación, podrás habilitar el nuevo editor de definiciones de versión, tal como


se muestra en la siguiente captura de pantalla:

Vamos a comenzar la creación de una nueva definición de versión.

[ 350 ]
Capítulo 11

Cómo hacerlo...
Sigue estos pasos:

1. Ve a la pestaña Versiones, tal como se muestra en la siguiente captura


de pantalla. Haz clic en el enlace Nueva canalización:

2. El siguiente paso es seleccionar una plantilla de definición de versión. En


el cuadro emergente Seleccionar una plantilla, elige Implementación de
Azure App Service y haz clic en el botón Aplicar, tal como se muestra en
la siguiente captura de pantalla. Inmediatamente después de hacer clic en
el botón Aplicar, se mostrará el cuadro emergente del nuevo entorno (fase).
Por ahora, cierra el cuadro emergente Entorno:

[ 351 ]
Implementar la integración continua mediante Azure DevOps

3. Haz clic en el botón Agregar disponible en el cuadro Artefactos para añadir


un nuevo artefacto, tal como se muestra en la siguiente captura de pantalla:

[ 352 ]
Capítulo 11

4. En el cuadro emergente Agregar un artefacto, asegúrate de elegir lo


siguiente:
1. Tipo de origen: Compilación
2. Proyecto: el proyecto de equipo al que está vinculado el código
fuente
3. Origen (definición de compilación): el nombre de la definición
de compilación en la que se crean las compilaciones
4. Versión predeterminada: Más reciente

5. Después de revisar todos los valores de la página, haz clic en el botón


Agregar para añadir el artefacto.
6. Cuando se añada el artefacto, el siguiente paso será configurar las fases en
las que el paquete se debe publicar. Haz clic en el enlace 1 fase, 1 tarea que se
muestra en la siguiente captura de pantalla. Además, cambia el nombre de la
definición de versión por release-def-stg:
[ 353 ]
Implementar la integración continua mediante Azure DevOps

7. Se te dirigirá a la pestaña Tareas que se muestra a continuación. Proporciona


un nombre descriptivo en el campo Nombre de fase. He utilizado el nombre
Entorno de ensayo para este ejemplo. A continuación, selecciona la
suscripción de Azure en la que te gustaría implementar la función de Azure.
Haz clic en el botón Autorizar para otorgar permisos, tal como se muestra
a  continuación:

[ 354 ]
Capítulo 11

8. Tras autorizar la suscripción, asegúrate de indicar que el Tipo de aplicación


es Aplicación de función. A continuación, elige el nombre de la aplicación de
función en el Nombre de App Service para el que te gustaría implementar el
paquete, tal como se muestra a continuación:

Si no ves la suscripción ni App Service, actualiza el


elemento. Para ello, haz clic en el icono disponible
después del botón Autorizar de la captura de pantalla
anterior.

9. Haz clic en el botón Guardar para guardar los cambios. Ahora vamos
a utilizar la definición de versión para intentar crear una nueva versión
mediante el clic en Crear versión, tal como se muestra en la siguiente captura
de pantalla:

[ 355 ]
Implementar la integración continua mediante Azure DevOps

10. A continuación, accederás al cuadro emergente Crear nueva versión donde


podrás configurar la definición de compilación que se debe utilizar. Como
solo tenemos una, solo podemos ver una definición de compilación. También
debes elegir la versión correcta de la compilación, tal como se muestra
a continuación. Cuando la revises, haz clic en el botón Crear para poner la
versión en cola:

[ 356 ]
Capítulo 11

11. Al hacer clic en el botón Crear del paso anterior, pasarás al paso siguiente.
Haz clic en el botón Implementar fase, tal como se muestra a continuación,
para iniciar el proceso de implementación de la versión:

12. Ahora se te solicitará que revises los artefactos asociados. Cuando lo hayas
hecho, haz clic en el botón Implementar que se muestra a continuación:

[ 357 ]
Implementar la integración continua mediante Azure DevOps

13. El proceso comenzará inmediatamente y mostrará En curso para indicar el


progreso de la versión, tal como se indica a continuación:

[ 358 ]
Capítulo 11

14. Haz clic en los enlaces En curso que se muestran en la captura de pantalla
anterior para revisar el progreso. Como se muestra a continuación, el proceso
de creación de la versión ha funcionado correctamente:

Cómo funciona...
En la pestaña Canalización, hemos creado artefactos y un entorno denominado
ensayo y los hemos vinculado.

También hemos configurado el entorno para que Azure App Service se relacione
con las Azure Functions que hemos creado en el capítulo 4, Comprender la experiencia
de desarrollador integrada de Visual Studio Tools para Azure Functions.

Y eso no es todo…
Si vas a configurar una implementación continua por primera vez, es posible que
veas un botón con el texto Autorizar en el paso Implementación de Azure App
Service. Al hacer clic en el botón Autorizar, se abrirá una ventana emergente en la
que se te pedirán las credenciales del portal de administración de Azure.

Para cambiar el nombre de la canalización de versión, haz clic en el nombre en la


parte superior, tal como se muestra a continuación:

[ 359 ]
Implementar la integración continua mediante Azure DevOps

En la actualidad existe una plantilla específica de Azure Functions, que se muestra


a continuación. Sin embargo, parece que no funciona. Cuando leas este documento,
intenta lo siguiente:

Consulta también
La receta Implementación de una aplicación de función de Azure en el cloud de Azure
mediante Visual Studio del capítulo 4, Comprender la experiencia de desarrollador integrada
de Visual Studio Tools para Azure Functions.

[ 360 ]
Capítulo 11

Desencadenar la versión
automáticamente
En esta receta, aprenderás a configurar la implementación continua de un entorno.
En el proyecto puedes configurar desarrollo/ensayo o cualquier otro entorno
de preproducción y configurar la implementación continua para optimizar el proceso
de implementación.

En general, no se recomienda configurar la implementación continua para un


entorno de producción. Sin embargo, esto puede depender de distintos factores
y requisitos. Ten cuidado y piensa en las distintas situaciones posibles antes de
configurar la implementación continua para el entorno de producción.

Preparación
Si aún no has instalado la herramienta Postman, descárgala e instálala.

Cómo hacerlo...
Sigue estos pasos:

1. De forma predeterminada, las versiones se configuran para insertarse


manualmente. Vamos a configurar la implementación continua. Para ello,
vamos a volver a la pestaña Canalización y a hacer clic en Desencadenador
de implementación continua, tal como se muestra en la siguiente captura
de pantalla:

[ 361 ]
Implementar la integración continua mediante Azure DevOps

2. Tal como se muestra en la siguiente captura de pantalla, activa el


Desencadenador de implementación continua y haz clic en Guardar para
guardar los cambios:

3. Ve a Visual Studio y aplica los cambios al código que se indican


a continuación:
return name != null ? (ActionResult)new OkObjectResult($"Automated
Build Trigger and Release test by, { name}")
: new BadRequestObjectResult("Please pass a name on the
query string or in the request body");

4. Ahora, inserta el código con un comentario, Implementación continua,


para confirmar los cambios de Azure DevOps. En cuanto insertes el código,
dirígete a la pestaña Compilaciones para ver cómo se desencadena una
nueva compilación, tal como se muestra en la siguiente captura de pantalla:

[ 362 ]
Capítulo 11

5. Ve a la pestaña Versiones tras completar la compilación para ver la


activación automática de una nueva versión, tal como se muestra en la
siguiente captura de pantalla:

6. Cuando el proceso de creación de la versión se haya completado, podrás


revisar el cambio mediante una solicitud al desencadenador de HTTP con la
herramienta Postman:

Cómo funciona...
En la pestaña Canalización, hemos habilitado el Desencadenador
de implementación continua.

Cada vez que se desencadena una compilación asociada con


AzureServerlessCookBook-C# Function-CI, se activa automáticamente
la versión del libro de instrucciones sin servidor de Azure para
implementar la última compilación en el entorno designado. También hemos visto en
acción la creación automática de versiones mediante un cambio del código en Visual
Studio.

Y eso no es todo…
También puedes crear distintos entornos y configurar las definiciones para publicar
las compilaciones necesarias en estos entornos.
[ 363 ]
Otros libros que te podrían
gustar
Si te ha gustado este libro, puede que te interesen estos otros libros de Packt:

Architecting Microsoft Azure Solutions – Exam Guide 70-535


Sjoukje Zaal
ISBN: 978-1-78899-173-5
ff Utiliza máquinas virtuales de Azure para diseñar implementaciones de MV efectivas
ff Implementa estilos de arquitectura, como la informática sin servidor y los
microservicios
ff Protege tus datos utilizando diferentes funciones de seguridad y diseña
estrategias de seguridad efectivas
ff Diseña soluciones de almacenamiento de Azure utilizando diversas funciones
de almacenamiento
ff Crea soluciones de gestión de identidades para tus aplicaciones y recursos
ff Diseña soluciones de vanguardia con inteligencia artificial, IoT y Azure Media
Services
ff Utiliza diferentes soluciones de automatización que están incorporadas en la plataforma
de Azure
364
Otros libros que te podrían gustar

Hands-On Linux Administration on Azure

Frederik Vos

ISBN: 978-1-78913-096-6

ff Descubre por qué Azure es la solución ideal para tus cargas de trabajo de código
abierto
ff Domina las habilidades esenciales de Linux y aprende a encontrar tu camino
en el entorno Linux
ff Implementa Linux en un entorno de Azure
ff Utiliza la administración de configuración para administrar Linux en Azure
ff Administra contenedores en un entorno de Azure
ff Mejora la seguridad de Linux y usa los sistemas de gestión de identidades
de Azure
ff Automatiza la implementación con Azure Resource Manager (ARM)
y Powershell
ff Utiliza Ansible para administrar instancias de Linux en un entorno en el cloud
de  Azure

365
Otros libros que te podrían gustar

Deja un comentario para que otros


lectores sepan lo que opinas
Comparte tu opinión sobre este libro con otras personas dejando un comentario en el
sitio en el que lo compraste. Si lo compraste en Amazon, danos tu sincera opinión sobre
el libro en la página de Amazon. Esto es muy importante, porque de esta forma otros
lectores potenciales podrán ver y utilizar tu opinión para decidir si lo compran. También
nos sirve para saber qué opinan nuestros clientes sobre nuestros productos y para que
los autores lean tus comentarios sobre el título que han creado en colaboración con Packt.
Solo te llevará unos minutos, pero resultará muy útil para otros clientes potenciales,
nuestros autores y Packt.

366

Você também pode gostar