Sunteți pe pagina 1din 393

Informática

sin servidor de
Azure
Manual Segunda edición

Tareas para compilar y supervisar aplicaciones controladas por eventos utilizando


Azure Functions

www.packt.com
Praveen Kumar Sreeram
Manual de informática sin
servidor de Azure
Segunda edición

Tareas para compilar y supervisar aplicaciones


controladas por eventos utilizando Azure Functions

Praveen Kumar Sreeram

BIRMINGHAM - BOMBAY
Manual de informática sin servidor de Azure
Segunda edición
Copyright © 2018 Packt Publishing

Todos los derechos reservados. No está permitida la reproducción, el almacenamiento en


un sistema de recuperación ni la transmisión en cualquier formato o por cualquier medio
de cualquier parte de este libro sin la autorización previa y por escrito del editor, salvo en
el caso de citas breves introducidas en artículos o revistas de opinión crítica.

Durante la preparación de este libro, se hizo todo lo posible por asegurar la exactitud
de la información presentada. Sin embargo, los datos que contiene este libro se
venden sin garantía, ya sea expresa o implícita. Ni el autor ni Packt Publishing, sus
concesionarios y distribuidores se considerarán responsables de cualquier daño causado
o presuntamente causado de manera directa o indirecta por el contenido de este libro.

Packt Publishing intentó proporcionar información de marca registrada de todas las


empresas y los productos mencionados en este libro mediante el uso adecuado de
mayúsculas. Sin embargo, Packt Publishing no garantiza la exactitud de esta información.

Editor a cargo: Vijin Boricha


Directora editorial: Shrilekha Inani
Editores de desarrollo de contenido: Nithin George Varghese
Editor técnico: Komal Karne
Corrector de estilo: Safis Editing
Coordinador del proyecto: Drashti Panchal
Revisor: Safis Editing
Indexador: Mariammal Chettiyar
Gráficos: Tom Scaria
Coordinador de producción: Aparna Bhagat

Fecha de 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 hubiera sido posible completar este libro sin el apoyo de mi otra mitad, mi esposa,
Haritha, y mi pequeño y bello ángel, Rithwika Sreeram.
mapt.io

Mapt es una biblioteca digital en línea que brinda acceso completo a más de 5.000
libros y videos, así como también a importantes herramientas, para ayudarlo
a planificar su desarrollo personal y a avanzar en su profesión. Para obtener más
información, visite nuestro sitio web.

¿Por qué suscribirse?


• Pase menos tiempo aprendiendo y más tiempo codificando con los prácticos
eBooks y videos realizados por más de 4.000 profesionales de la industria
• Aprenda mejor con los planes de habilidades desarrollados especialmente
para usted
• Reciba un eBook o video gratuito cada mes
• Mapt es plenamente accesible
• Contenido que se puede copiar y pegar, imprimir y marcar como favorito

PacktPub.com
¿Sabía que Packt ofrece versiones de eBook de cada libro publicado, con
archivos PDF y ePub disponibles? Puede actualizar a la versión de eBook en
www.PacktPub.com y, como compró la versión impresa del libro, tiene derecho
a un descuento en la copia del eBook. Para obtener más información, comuníquese
con nosotros a la dirección service@packtpub.com.

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


gratuitos, registrarse para recibir una variedad de boletines informativos sin cargo
y recibir descuentos y ofertas exclusivas en libros e eBooks de Packt.
Colaboradores

Acerca del autor


Praveen Kumar Sreeram trabaja como arquitecto de Azure, es instructor en
un MNC líder. Tiene más de 14 años de experiencia en el campo del desarrollo,
el análisis, el diseño y la entrega de aplicaciones, incluido el desarrollo web
personalizado utilizando ASP.NET y MVC para compilar aplicaciones móviles con
Xamarin para dominios como empresas de seguros, telecomunicaciones
y administración de gastos inalámbricos. Fue reconocido dos veces como MVP por
uno de los principales sitios web de la comunidad social, CSharpCorner. Es un ávido
blogger que escribe sobre su aprendizaje en su blog personal, llamado Praveen
Kumar Sreeram. Su enfoque actual es el análisis de problemas comerciales y la
prestación de soluciones técnicas para diversos proyectos relacionados con Microsoft
Azure y .NET Core. Su ID de Twitter es @PrawinSreeram.

En primer lugar, quiero agradecerle al equipo de Packt Publishing,


entre ellos, Shrilekha Inani, Nithin George Varghese y Komal Karne.

Me gustaría agradecerle a mi abuela, Neelavatamma, a mi padre,


Kamalakar y a mi madre, Seetha, por ser parte de mi vida y por alentarme
todo el tiempo.

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


Kamala Kumar (mi tío materno), sus hermanos y al resto de la familia, que
me apoyaron todo el tiempo.
Acerca de los revisores
Kasam Shaikh, entusiasta de Microsoft Azure, es un profesional experimentado
con una actitud optimista. Con 10 años de experiencia en la industria, trabaja como
arquitecto en la nube con una de las principales empresas de TI en Bombay, India.
Es un arquitecto certificado de Azure, fue reconocido como MVP por una comunidad
en línea muy importante y también es un orador global sobre IA. Escribió libros
sobre Azure Cognitive, Azure Bots y Microsoft Bot Frameworks. Lidera la
comunidad de Azure India (AZINDIA), la comunidad en línea de más rápido
crecimiento para el aprendizaje de Azure. También es fundador del sitio web
Dear Azure.

Ante todo, me gustaría agradecerle a Dios Todopoderoso, a mi familia


y, especialmente, a mi otra mitad por motivarme a lo largo de este
proceso. Estoy muy agradecido a Packt Publishing por creer en mí y por
considerarme para esta oportunidad.

Michael Sync (SOE Htike) es un ingeniero sénior que trabaja en Readify en


Australia. Fue MVP (profesional más valioso de Microsoft) durante 7 años. Participó
como orador, mentor y ayudante en varios eventos comunitarios. También es autor
y revisor de libros de tecnología. Publicó dos libros con Manning y revisó varios
libros para una serie de editores. Ha estado trabajando en la industria del software
por más de 16 años.

Packt busca autores como usted


Si le interesa convertirse en autor para Packt, visite authors.packtpub.com
y presente una solicitud hoy mismo. Hemos trabajado con miles de desarrolladores
y profesionales técnicos como usted, para ayudarles a compartir sus conocimientos
con la comunidad tecnológica mundial. Puede presentar una solicitud general,
postular a un tema popular específico para el que estemos reclutando un autor,
o bien, puede enviar su propia idea.
Tabla de contenido
Prólogoxiii
Capítulo 1: Desarrollo de aplicaciones en la nube utilizando
desencadenadores de funciones y enlaces 1
Introducción1
Compilación de una API web de back-end
utilizando desencadenadores HTTP 2
Preparación3
Procedimiento...3
Funcionamiento...8
Consulte también 8
Mantenimiento de datos de los empleados utilizando
enlaces de salida de tablas de Azure Storage 8
Preparación9
Procedimiento...9
Funcionamiento...13
Comprender la conexión de almacenamiento 14
¿Qué es el servicio de Almacenamiento de tablas de Azure? 15
Clave de partición y clave de fila 15
Aún hay más... 15
Guardado de imágenes de perfil en colas utilizando
enlaces de salida de cola 15
Preparación16
Procedimiento...16
Funcionamiento...18
Almacenamiento de la imagen en el Almacenamiento
de blobs de Azure 18
Preparación18
Procedimiento...18
Funcionamiento...20
Aún hay más... 21
[i]
Contenido

Capítulo 2: Trabajar con notificaciones utilizando los


servicios SendGrid y Twilio 23
Introducción23
Envío de una notificación por correo electrónico al administrador
de un sitio web utilizando el servicio SendGrid 24
Preparación24
Crear 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 Functions 28
Procedimiento...28
Crear un enlace de cola de almacenamiento para el desencadenador HTTP 29
Crear un desencadenador de cola para procesar el mensaje del
desencadenador HTTP 30
Crear un enlace de salida de SendGrid para el desencadenador de cola 31
Funcionamiento...33
Aún hay más... 34
Envío de una notificación por correo electrónico
de manera dinámica al usuario final 34
Preparación34
Procedimiento...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
Funcionamiento...37
Aún hay más... 38
Implementación del registro de correo electrónico
en el Almacenamiento de blobs de Azure 39
Procedimiento...39
Funcionamiento...41
Modificación del contenido de un correo electrónico
para incluir un archivo adjunto 41
Preparación42
Procedimiento...42
Personalizar el nombre del archivo de registro a través de la interfaz IBinder 42
Agregar un archivo adjunto al correo electrónico 43
Envío de una notificación por SMS al usuario final
utilizando el servicio Twilio 44
Preparación45
Procedimiento...47
Funcionamiento...49
Capítulo 3: Integración perfecta de Azure Functions con
los servicios de Azure 51
Introducción51

[ ii ]
Contenido

Uso de Cognitive Services para ubicar rostros en imágenes 52


Preparación52
Crear una nueva cuenta de Computer Vision API 52
Configurar la aplicación 53
Procedimiento...53
Funcionamiento...60
Aún hay más... 60
Interacciones de Azure SQL Database con Azure Functions 61
Preparación61
Procedimiento...63
Funcionamiento...66
Supervisión de tweets utilizando Logic Apps y notificar a los
usuarios cuando un usuario popular publica en esta red social 66
Preparación67
Procedimiento...67
Crear una aplicación lógica nueva 67
Diseñar la aplicación lógica con conectores de Twitter y Gmail 69
Probar la funcionalidad de la aplicación lógica 73
Funcionamiento...74
Integración de Logic Apps con funciones sin servidor 74
Procedimiento...75
Aún hay más... 79
Consulte también 80
Auditoría de datos de Cosmos DB utilizando desencadenadores
de fuente de cambios 80
Preparación80
Crear una cuenta de Cosmos DB nueva 81
Crear una colección de Cosmos DB nueva 81
Procedimiento...82
Funcionamiento...86
Aún hay más... 86
Capítulo 4: Comprender la experiencia integrada
de desarrollador de Visual Studio Tools 87
Introducción87
Creación de una aplicación de función utilizando
Visual Studio 2017 88
Preparación88
Procedimiento...90
Funcionamiento...92
Aún hay más... 92

[ iii ]
Contenido

Depuración de funciones de Azure C# en un entorno


local previamente configurado utilizando Visual Studio 2017 92
Preparación93
Procedimiento...93
Funcionamiento...97
Aún hay más... 97
Conexión con la nube de Azure Storage desde el entorno
local de Visual Studio 98
Preparación98
Procedimiento...98
Funcionamiento...102
Aún hay más... 102
Implementación de la aplicación de función de Azure
en la nube de Azure utilizando Visual Studio 103
Procedimiento...103
Aún hay más... 107
Depuración de una función de Azure C# activa hospedada
en el entorno de nube de Microsoft Azure con Visual Studio 107
Preparación108
Procedimiento...108
Implementación de las funciones de Azure en un contenedor 111
Preparación112
Crear un ACR 113
Procedimiento...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
Funcionamiento...119
Capítulo 5: Explorar las herramientas de prueba
para validar las funciones de Azure 121
Introducción121
Prueba de las funciones de Azure 122
Preparación122
Procedimiento...123
Probar los desencadenadores HTTP utilizando Postman 123
Probar un desencadenador de blobs utilizando el explorador
de almacenamiento de Microsoft 125
Probar el desencadenador de cola utilizando el portal
de administración de Azure 128
Aún hay más... 131

[ iv ]
Contenido

Prueba de una función de Azure en un entorno previamente


configurado utilizando ranuras de implementación 131
Procedimiento...132
Aún hay más... 139
Prueba de carga de las funciones de Azure mediante
Azure DevOps 139
Preparación140
Procedimiento...140
Aún hay más... 143
Consulte también 144
Creación y prueba de las funciones de Azure de manera local
con herramientas de la CLI de Azure 144
Preparación145
Procedimiento...145
Prueba y validación de la capacidad de respuesta
de una función de Azure utilizando Application Insights 148
Preparación149
Procedimiento...150
Funcionamiento...153
Aún hay más... 153
Desarrollo de pruebas unitarias para las funciones
de Azure con desencadenadores HTTP 153
Preparación154
Procedimiento...155
Capítulo 6: Supervisar y solucionar problemas en los
servicios sin servidor de Azure 158
Introducción158
Solución de problemas relacionados con las
funciones de Azure 159
Procedimiento...159
Consultar registros de aplicaciones en tiempo real 159
Diagnosticar toda la aplicación de función 161
Aún hay más... 162
Integración de las funciones de Azure con Application Insights 164
Preparación164
Procedimiento...165
Funcionamiento...167
Aún hay más... 167
Supervisión de las funciones de Azure 167
Procedimiento...167
Funcionamiento...169
[v]
Contenido

Inserción de detalles de telemetría personalizados


en Application Insights Analytics 169
Preparación171
Procedimiento...171
Crear una función de Application Insights 172
Configurar claves de acceso 173
Integrar y probar una consulta de
Application Insights 175
Configurar el informe de una métrica
derivada personalizada 177
Funcionamiento...179
Envío de detalles de telemetría de aplicación
por correo electrónico 180
Preparación180
Procedimiento...181
Funcionamiento...183
Aún hay más... 183
Consulte también 183
Integración de datos de supervisión de Application
Insights en tiempo real con Power BI utilizando
Azure Functions 183
Preparación184
Procedimiento...185
Configurar Power BI con un panel, un conjunto de datos y una URL de inserción 185
Crear una función C# de Power BI en tiempo real para Azure Application Insights 191
Funcionamiento...194
Aún hay más... 194
Capítulo 7: Desarrollar aplicaciones sin servidor fiables
con Durable Functions 195
Introducción195
Configuración de Durable Functions en el portal
de administración de Azure 196
Preparación196
Procedimiento...197
Aún hay más... 198
Creación de una aplicación HelloWorld para Durable Function 199
Preparación199
Procedimiento...199
Crear la función HttpStart en el cliente de Orchestrator 200
Crear la función de Orchestrator 202
Crear una función de actividad 204
Funcionamiento...205

[ vi ]
Contenido

Aún hay más... 205


Prueba y solución de problemas en Durable Functions 205
Preparación206
Procedimiento...206
Implementación de aplicaciones fiables multiprocesos
con Durable Functions 208
Preparación208
Procedimiento...209
Crear la función de Orchestrator 209
Crear la función de actividad GetAllCustomers  210
Crear la función de actividad CreateBARCodeImagesPerCustomer 211
Funcionamiento...213
Aún hay más... 213
Capítulo 8: Importación masiva de datos utilizando
Azure Durable Functions y Cosmos DB 215
Introducción215
Problema comercial 216
Enfoque sin servidor duradero para implementar
la importación de Excel 217
Carga de datos de los empleados en Almacenamiento de blobs 217
Procedimiento...218
Funcionamiento...221
Aún hay más... 222
Creación de un desencadenador de blobs 222
Preparación222
Procedimiento...226
Aún hay más... 226
Creación del orquestador durable y desencadenarlo
para cada importación de Excel 227
Procedimiento...227
Funcionamiento...230
Aún hay más... 230
Lectura de datos de Excel utilizando funciones de actividad 231
Preparación231
Procedimiento...232
Leer datos del Almacenamiento de blobs 232
Leer los datos de Excel de la secuencia 233
Crear la función de actividad 234
Aún hay más... 236
Escalado automático del rendimiento de Cosmos DB 237
Preparación237

[ vii ]
Contenido

Procedimiento...239
Aún hay más... 241
Inserción masiva de datos en Cosmos DB 241
Procedimiento...241
Aún hay más... 242
Capítulo 9: Implementar procedimientos recomendados
para Azure Functions243
Incorporación de varios mensajes a una cola utilizando
la función IAsyncCollector 244
Preparación244
Procedimiento...245
Funcionamiento...247
Aún hay más... 247
Implementación de aplicaciones defensivas con
Azure Functions y desencadenadores de cola 247
Preparación248
Procedimiento...248
Aplicar la consola, CreateQueueMessage, mediante C# 248
Desarrollar la función de Azure, desencadenador de cola 249
Ejecutar pruebas utilizando la aplicación de consola 250
Funcionamiento...251
Aún hay más... 251
Control del ingreso masivo utilizando Event Hubs
para IoT y otros escenarios similares 252
Preparación252
Procedimiento...252
Crear un desencadenador de Event Hub para una función de Azure 252
Desarrollar una aplicación de consola que simule datos de IoT  253
Prevención de arranques en frío activando la aplicación
a intervalos constantes 256
Preparación256
Procedimiento...257
Crear un desencadenador HTTP 257
Crear un desencadenador de temporizador 257
Aún hay más... 258
Consulte también 258
Habilitación de la autorización para aplicaciones de función 258
Preparación258
Procedimiento...259
Funcionamiento...260
Aún hay más... 260

[ viii ]
Contenido

Control de acceso a funciones de Azure utilizando


claves de función 260
Procedimiento...261
Configurar la clave de función para cada aplicación 261
Configurar una clave de host para todas las funciones en una única
aplicación de función 262
Aún hay más... 264
Protección de las funciones de Azure utilizando
Azure Active Directory 264
Preparación265
Procedimiento265
Configurar Azure AD para la aplicación de función 265
Registrar la aplicación cliente en Azure AD 266
Permitirle a la aplicación cliente que acceda a la aplicación de back-end 269
Probar la funcionalidad de autenticación utilizando un token de JWT 269
Configuración de la limitación de Azure Functions
utilizando API Management 271
Preparación272
Procedimiento...273
Integrar Azure Functions con API Management 273
Configurar la limitación de solicitudes utilizando directivas de entrada 276
Probar la configuración de las directivas de entrada para el límite de velocidad 278
Funcionamiento...279
Acceso seguro a SQL Database desde Azure Functions
utilizando Managed Service Identity 280
Preparación280
Procedimiento...281
Crear una aplicación de función utilizando Visual Studio 2017
con el tiempo de ejecución de la v1 281
Crear un servidor SQL Server lógico y una base de datos SQL 284
Habilitar Managed Service Identity 284
Aún hay más... 287
Consulte también 287
Código compartido entre las funciones de Azure utilizando
bibliotecas de clases 287
Procedimiento...288
Funcionamiento...290
Aún hay más... 291
Uso de clases fuertemente tipadas en Azure Functions 291
Preparación291
Procedimiento...292
Funcionamiento...294
Aún hay más... 294

[ ix ]
Contenido

Capítulo 10: Configurar aplicaciones sin servidor


en el entorno de producción 295
Introducción295
Implementación de Azure Functions con Run From Package 296
Preparación297
Procedimiento...298
Funcionamiento...299
Aún hay más... 299
Implementación de la función de Azure utilizando plantillas de ARM 299
Preparación299
Procedimiento...300
Aún hay más... 303
Configuración de un dominio personalizado en Azure Functions 303
Preparación304
Procedimiento...304
Configurar la aplicación de función con un dominio existente 306
Técnicas para acceder a la configuración de aplicaciones 308
Preparación308
Procedimiento...308
Acceder a la configuración de la aplicación y a las cadenas
de conexión en el código de la función de Azure 308
Configuración de la aplicación: expresiones de enlace 311
Creación y generación de especificaciones
de API abiertas utilizando Swagger 311
Preparación312
Procedimiento...312
Descomposición de grandes API en pequeños
subconjuntos de API utilizando proxies 316
Preparación316
Procedimiento...317
Crear microservicios 318
Crear los proxies de gateway 318
Probar las URL de proxy 321
Aún hay más... 321
Consulte también 322
Migración de elementos de configuración
de un entorno a otro utilizando recursos 322
Preparación323
Procedimiento...324
Capítulo 11: Implementar y facilitar la integración continua
utilizando Azure DevOps 329

[x]
Contenido

Introducción329
Requisitos previos 330
Integración continua: crear una definición de compilación 331
Preparación332
Procedimiento...333
Funcionamiento...337
Aún hay más... 338
Integración continua: poner en cola una compilación
y desencadenarla de forma manual 338
Preparación338
Procedimiento...339
Configuración y desencadenamiento de una
compilación automatizada 341
Procedimiento...342
Funcionamiento...344
Aún hay más... 344
Integración continua: ejecutar casos de prueba
unitaria en la canalización 345
Procedimiento...346
Aún hay más... 348
Creación de una definición de versión 348
Preparación349
Procedimiento...350
Funcionamiento...358
Aún hay más... 358
Consulte también 359
Desencadenamiento de la versión automáticamente 360
Preparación360
Procedimiento...360
Funcionamiento...362
Aún hay más... 362
Otros libros que puede disfrutar 363

[ xi ]
Prólogo

Prólogo
La informática sin servidor es la abstracción de la administración de infraestructura
y permite que los desarrolladores aumenten su enfoque en la lógica de negocios para
que puedan ofrecer más características e innovación por ciclo. Al compilar aplicaciones
sin servidor, no tiene que invertir tiempo en el aprovisionamiento o la administración
de la infraestructura (por ejemplo, crear servidores, instalar actualizaciones, aplicar
parches al sistema operativo, administrar el escalado de la aplicación). En cambio,
emplea un conjunto de servicios en la nube totalmente administrados y altamente
escalables que se encargan de esa parte del trabajo.
Los beneficios de la informática sin servidor abarcan toda la organización y el ciclo
de desarrollo:
• Para el desarrollador, representa el enfoque pleno en el valor. La compilación
de aplicaciones sin servidor aumenta la capacidad individual de contribuir
de forma más eficaz a las áreas centrales 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 facilitador de la innovación desde una base
sólida. Gracias a la combinación de capacidad liberada y servicios
disruptivos, toda la organización puede actuar a partir de las primeras
señales para desarrollar o diversificar su modelo de negocio y cumplir con su
agenda de innovación.
Cuando se habla de aplicaciones sin servidor, podemos identificar algunos patrones
de aplicación que vale la pena mencionar aquí. Mientras que cada uno de ellos
comparte los beneficios indicados anteriormente, también tienen características
específicas y beneficios adicionales que los hacen únicos y los convierte en una mejor
opción para ciertos escenarios. Podemos observar los siguientes patrones en las
aplicaciones sin servidor:
• Aplicaciones web que hospedan tanto el lado del cliente como el del back-
end en servicios totalmente administrados que gestionan los requisitos de
escalado automático, seguridad y cumplimiento con App Service.
[ xiii ]
Prólogo

• Aplicaciones controladas por eventos que utilizan funciones sin servidor,


aprovechando el modelo de programación exclusivo (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.
• Flujos de trabajo con poco código para una orquestación fácil y rápida de
tareas combinadas que resuelven un problema comercial (normalmente
integrando diferentes servicios, tanto en la nube como en el entorno local,
para trabajar juntos), sin codificar en verdad esas integraciones ni aprender
nuevas API o especificaciones, con Logic Apps.
• Contenedores sin servidor, que traen sus propios contenedores a una
orquestación de Kubernetes totalmente administrada con Azure Kubernetes
Service, que puede realizar el escalado de ráfagas con nodos virtuales
y Azure Container Instances cuando el volumen de la carga de trabajo se
escala de forma repentina o brusca.
Microsoft brinda una solución para ejecutar fácilmente pequeños segmentos de
código en la nube con Azure Functions. Azure Functions aporta soluciones para
el procesamiento de datos, la integración de sistemas y la compilación de API
y microservicios sencillos.
El libro comienza con tareas de nivel intermedio sobre la informática sin servidor,
junto con algunos casos de uso sobre las ventajas y las características clave de Azure
Functions. Luego se examinan los aspectos más importantes de Azure Functions,
como los servicios que proporciona, cómo desarrollar y escribir funciones de Azure,
y cómo supervisarlas y resolver los problemas que surgen en ellas.
Más adelante, se presentan tareas 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 incluye pasos y tutoriales prácticos
basados en casos de uso reales de informática sin servidor para ayudarlo a configurar
sus entornos sin servidor con facilidad. Finalmente, verá cómo administrar funciones
de Azure, brindando seguridad empresarial y cumplimiento a su arquitectura de
código sin servidor.
También aprenderá a compilar rápidamente aplicaciones 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á todas las habilidades necesarias para trabajar con
arquitecturas de código sin servidor, proporcionando una entrega continua
a los usuarios.

Quiénes son los destinatarios de este libro


Si es un administrador, arquitecto o desarrollador de la nube que desea compilar
sistemas escalables e implementar aplicaciones sin servidor con Azure Functions, el
Manual de informática sin servidor de Azure es para usted.

[ xiv ]
Prólogo

Qué se analiza en este libro


El Capítulo 1, Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones
y enlaces, aborda cómo el tiempo de ejecución de las funciones de Azure proporciona
plantillas que se pueden utilizar para integrar rápidamente diferentes servicios de
Azure para las necesidades de su aplicación. Reduce todos los códigos "plumbing"
para que usted pueda enfocarse de lleno en la lógica de la aplicación. En este
capítulo, aprenderá a compilar una API web y enlaces relacionados con los servicios
de Azure Storage.

En el Capítulo 2, Trabajar con notificaciones utilizando los servicios SendGrid y Twilio,


se explica por qué la comunicación es uno de los aspectos más fundamentales de
cualquier requerimiento empresarial. En este capítulo, aprenderá lo fácil que es
conectar los 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 puede aprovechar para integrar sus
aplicaciones empresariales con otros sistemas con bastante facilidad. En este capítulo,
aprenderá a integrar Azure Functions con Cognitive Services y Logic Apps.

En el Capítulo 4, Comprender la experiencia integrada del desarrollador de Visual Studio


Tools para Azure Functions, aprenderá a desarrollar funciones de Azure utilizando
Visual Studio, que le ofrece muchas características, como IntelliSense, depuración
local y remota, y la mayoría de las características de desarrollo habituales.

En el Capítulo 5, Explorar las herramientas de prueba para validar las funciones de Azure,
comprenderá diferentes herramientas y procesos que le ayudan a agilizar sus
procesos de desarrollo y control de la calidad. También aprenderá a crear cargas
utilizando pruebas de carga de Azure DevOps (antes VSTS) y verá cómo supervisar
el rendimiento de Azure Functions utilizando los informes proporcionados por
Application Insights. Finalmente, también le enseñaremos cómo configurar alertas
que le informan cuando sus aplicaciones no responden.

El Capítulo 6, Supervisar y solucionar problemas en los servicios sin servidor de Azure, le


enseña a supervisar continuamente las aplicaciones, analizar el rendimiento y revisar
los registros para saber si los usuarios finales están lidiando con algún tipo de problema.
Azure nos brinda varias herramientas para satisfacer todos los requisitos de supervisión,
directamente desde las fases de desarrollo y mantenimiento de la aplicación.

El Capítulo 7, Desarrollar aplicaciones sin servidor fiables con Durable Functions, le


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

[ xv ]
Prólogo

El Capítulo 8, Importación masiva de datos utilizando Azure Durable Functions y Cosmos


DB, le enseña a aprovechar las funciones duraderas de Azure para leer e importar los
datos desde el almacenamiento de blobs y volcarlos en Cosmos DB.

En el Capítulo 9, Implementar procedimientos recomendados para Azure Functions,


aprenderá algunos de los procedimientos recomendados que debe seguir para
aumentar el rendimiento y la seguridad mientras trabaja en Azure Functions.

En el Capítulo 10, Configurar aplicaciones sin servidor en el entorno de producción, se


demuestra cómo implementar una aplicación de función con eficiencia y copiar
o mover las configuraciones de un modo más inteligente para evitar errores
humanos. También aprenderá a configurar un dominio personalizado que puede
compartir con sus 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 y facilitar la integración continua utilizando Azure DevOps, le


enseña a implementar la integración y entrega continua del código de sus funciones
de Azure con la ayuda de Visual Studio y Azure DevOps.

Para sacar el máximo provecho


de este libro
Se requiere conocimiento previo y experiencia práctica sobre los servicios principales
de Microsoft Azure.

Descargue los archivos de código de ejemplo


Puede descargar los archivos de código de ejemplo de este libro desde su
cuenta en http://www.packtpub.com. Si compró este libro en otro lugar,
visite http://www.packtpub.com/support y regístrese para recibir los
archivos directamente por correo electrónico.

Siga estos pasos para descargar los archivos de código:

1. Inicie sesión o regístrese en http://www.packtpub.com.


2. Seleccione la pestaña SUPPORT.
3. Haga clic en Code Downloads & Errata.
4. Ingrese el nombre del libro en el cuadro de Búsqueda y siga las instrucciones
que aparecen en la pantalla.

[ xvi ]
Prólogo

Una vez que se haya descargado el archivo, asegúrese de descomprimir o extraer la


carpeta utilizando la versión más reciente de:

• WinRAR / 7-Zip para Windows


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

El paquete de código del 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ódigo
de nuestro enriquecido catálogo de libros y videos disponibles en
https://github.com/PacktPublishing/. ¡Deles un vistazo!

Descargue los archivos EPUB/mobi


y de código de ejemplo
Encontrará una versión EPUB y mobi de este libro en Github, sin cargo.

Descargue las imágenes a color


También ofrecemos un archivo PDF con imágenes a color de las capturas de pantalla
y los diagramas empleados en este libro. Puede descargarlo aquí: https://www.
packtpub.com/sites/default/files/downloads/9781789615265_ColorImages.pdf.

Convenciones utilizadas
Existen varias convenciones de texto que se utilizan en este libro.

CodeInText: Indica palabras de código en texto, nombres de la tabla de base de


datos, nombres de carpetas, nombres de archivos, extensiones de archivos, nombres
de ruta, URL ficticias, entrada del usuario e identificadores de Twitter. Por ejemplo:
"Monte el archivo de imagen de disco WebStorm-10*.dmg descargado como otro
disco en su sistema".

Un bloque de código se establece de la siguiente manera:


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

[ xvii ]
Prólogo

Cuando queremos llamar su atención hacia una parte específica de un bloque de


código, las líneas o los elementos pertinentes se resaltan en negrita:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

Las entradas o salidas de línea de comandos se escriben de la siguiente forma:


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

Negrita: Indica un nuevo término, una palabra importante o palabras que se ven en
la pantalla; por ejemplo, en menús o cuadros de diálogo, también aparecen en textos
como este. Este es un ejemplo: "Durante la instalación, elija Azure development en la
sección Workloads".

Las advertencias o notas importantes aparecen


en este formato.

Los trucos y sugerencias aparecen de esta


manera.

Secciones
En este libro, encontrará varios encabezados que aparecen con frecuencia
(Preparación, Procedimiento, Funcionamiento, Aún hay más... y Consulte también).

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

Preparación
Esta sección indica de qué se trata la tarea y describe cómo configurar el software
o la configuración preliminar requerida para la tarea.

Procedimiento
Esta sección contiene los pasos necesarios para seguir la tarea.

[ xviii ]
Prólogo

Funcionamiento
En general, en esta sección se explica detalladamente lo que sucedió
en la sección anterior.

Aún hay más...


Esta sección comprende información adicional sobre la tarea para que pueda
comprenderla mejor.

Consulte también
Esta sección contiene enlaces eficaces a otras fuentes de información útil para la tarea.

Póngase en contacto
Siempre estamos dispuestos a recibir los comentarios de nuestros lectores.

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


indique el título del libro en el asunto del mensaje. Si tiene preguntas acerca de algún
aspecto de este libro, envíenos un correo electrónico a questions@packtpub.com.

Fe de erratas: Si bien hicimos todo lo posible por asegurar la exactitud de nuestro


contenido, los errores ocurren. Si encuentra un error en este libro, le agradeceríamos
que nos informara de esto. Visite http://www.packtpub.com/submit-errata,
seleccione su libro, haga clic en el enlace Errata Submission Form (Formulario de
envío de fe de erratas) e ingrese los detalles.

Piratería: Si encuentra copias ilegales de nuestros trabajos en cualquier formato en


Internet, le agradeceríamos que nos proporcione la dirección de ubicación o el nombre
del sitio web. Póngase en contacto con nosotros en copyright@packtpub.com e
incluya un enlace al material.

Si le interesa convertirse en autor: Si hay un tema en el que tiene experiencia y le


interesa escribir o contribuir con un libro, visite http://authors.packtpub.com.

[ xix ]
Prólogo

Opiniones
Deje una reseña. Una vez que haya leído y utilizado este libro, ¿por qué no deja una
reseña en el sitio en el que lo compró? Entonces, los potenciales lectores podrán ver
y utilizar su opinión imparcial para tomar decisiones de compra, nosotros en Packt
podremos saber lo que piensa de nuestros productos y nuestros autores podrán ver
su opinión acerca del libro. ¡Gracias!

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

[ xx ]
Desarrollo de aplicaciones
en la nube utilizando
desencadenadores de
funciones y enlaces
En este capítulo, trataremos los siguientes temas:

• Compilación de una API web de back-end utilizando desencadenadores


HTTP
• Mantenimiento de datos de los empleados utilizando enlaces de salida de
tablas de Azure Storage
• Guardado de imágenes de perfil en colas utilizando enlaces de salida de cola
• Almacenamiento de la imagen en el Almacenamiento de blobs de Azure

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

[1]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

Azure Functions brinda muchas plantillas listas para utilizar que resuelven la
mayoría de los problemas comunes, como conectarse con el almacenamiento, crear
API web y recortar imágenes. En este capítulo, vamos a aprender cómo utilizar
estas plantillas incorporadas. Además de conocer los conceptos relacionados con
la informática sin servidor de Azure, intentaremos implementar una solución
que resuelve un problema de dominio básico: la creación de los componentes que
cualquier organización necesita para administrar la información de los empleados
internos.

A continuación encontrará un diagrama simple que le ayudará a entender el objetivo


de este capítulo:

Compilación de una API web de back-end


utilizando desencadenadores HTTP
Vamos a utilizar la arquitectura sin servidor de Azure para crear una API web
utilizando desencadenadores HTTP. Estos desencadenadores HTTP podrían ser
consumidos por cualquier aplicación de front-end capaz de realizar llamadas HTTP.

[2]
Capítulo 1

Preparación
Para empezar a comprender la informática sin servidor de Azure utilizando Azure
Functions, vamos a crear una API web de back-end básica que responda a las
solicitudes de HTTP.
• Consulte https://azure.microsoft.com/free/?&wt.mc_
id=AID607363_SEM_8y6Q27AS para crear una cuenta de Azure gratuita.
• Visite https://docs.microsoft.com/azure/azure-functions/
functions-create-function-app-portal para comprender el proceso
paso a paso para crear una aplicación de función y https://docs.
microsoft.com/azure/azure-functions/functions-create-first-
azure-function para crear una función. Al crear una función, también
se crea una cuenta de almacenamiento para guardar todos los archivos.
Recuerde el nombre de la cuenta de almacenamiento, ya que la utilizará más
adelante en otros capítulos.
• Una vez que cree la aplicación de función, repase los conceptos básicos de
desencadenadores y enlaces, que son esenciales para entender cómo funciona
Azure Functions. Antes de continuar, le recomiendo encarecidamente que
lea el artículo https://docs.microsoft.com/azure/azure-functions/
functions-triggers-bindings.

A lo largo del libro, utilizaremos C# como lenguaje de


programación. La mayoría de las funciones se desarrollan
utilizando el tiempo de ejecución de las funciones de Azure V2.
Sin embargo, hay algunas tareas que el tiempo de ejecución de
la V2 aún no admite, las que se mencionan en la tarea respectiva.
Esperamos que para cuando usted lea este libro, Microsoft
también haya habilitado esas características para el tiempo de
ejecución de la V2.

Procedimiento...
Lleve a cabo los pasos siguientes:
1. Ingrese a la página de listado Function App haciendo clic en el menú
Function Apps, ubicado en el extremo izquierdo.
2. Cree una nueva función haciendo clic en el icono +.

[3]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

3. Verá la página Azure Functions for .NET - getting started, donde tendrá
que elegir la clase de herramientas que desea utilizar. Puede elegir la que
le interese. Para los primeros capítulos, utilizaremos la opción In-portal,
ya que allí puede crear Azure Functions de forma rápida, directamente
desde el portal y sin utilizar ninguna herramienta. En los demás capítulos,
emplearemos Visual Studio y Azure Functions Core Tools para crear las
funciones.

4. A continuación, seleccione More templates y haga clic en Finish and view


templates como se muestra en esta captura de pantalla:

[4]
Capítulo 1

5. En la sección Choose a template below or go to the quickstart, elija la opción


HTTP trigger para crear una nueva función de desencadenador HTTP.

[5]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

6. Asígnele un nombre significativo. En este ejemplo, usé el nombre


RegisterUser para la función de Azure.
7. En el menú desplegable Authorization level, elija la opción Anonymous.
Profundizaremos en los detalles sobre todos los niveles de autorización en el
Capítulo 9, Implementar procedimientos recomendados para Azure Functions.

8. Haga clic en el botón Create para crear la función de desencadenador HTTP.


9. Después de crear la función, se crearán automáticamente todos los archivos
de configuración y código necesarios, y se abrirá el archivo run.csx para
que pueda editar el código. Reemplace el código predeterminado por el
siguiente código. He añadido dos parámetros (firstname y lastname), que
se mostrarán en la salida cuando se desencadene el desencadenador 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. Para guardar los cambios, haga clic en el botón Save ubicado arriba del
editor de código.
11. Vamos a probar la función RegisterUser utilizando la consola Test. Haga
clic en la pestaña Test para abrir la consola Test.

12. Ingrese los valores para firstname y lastname en la sección Request body.

Asegúrese de seleccionar POST en el menú desplegable HTTP method.

13. Una vez que haya revisado los parámetros de entrada, haga clic en el botón
Run, ubicado en el extremo inferior de la consola Test.

[7]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

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


todos los parámetros necesarios, aparecerá Status 200 OK y verá la salida en
la ventana Output, como se muestra en la captura de pantalla anterior.

Funcionamiento...
Ya creamos la primera función básica de Azure utilizando desencadenadores HTTP
e hicimos algunas modificaciones al código predeterminado. El código solo acepta
los parámetros firstname y lastname e imprime el nombre del usuario final con el
mensaje Hello {firstname} {lastname} como respuesta. También aprendimos
a probar la función del desencadenador HTTP directamente desde el portal de
administración de Azure.

Para hacerlo más simple, no validé el parámetro de


entrada. Asegúrese de validar todos los parámetros de
entrada en las aplicaciones que se ejecutan en su entorno
de producción.

Consulte también
La tarea Habilitar la autorización para aplicaciones de función en el Capítulo 9:
Implementar procedimientos recomendados para Azure Functions.

Mantenimiento de datos de los


empleados utilizando enlaces de
salida de tablas de Azure Storage
En la tarea anterior, aprendió a crear un desencadenador HTTP y a aceptar los
parámetros de entrada. Ahora vamos a trabajar en algo interesante, es decir, dónde
almacenar los datos de entrada en un medio persistente. Azure Functions nos
permite almacenar datos de muchas maneras. En este ejemplo, guardaremos los
datos en el Almacenamiento de tablas de Azure.

[8]
Capítulo 1

Preparación
En esta tarea, aprenderá lo fácil que es integrar un desencadenador HTTP y el
servicio de Almacenamiento de tablas de Azure utilizando enlaces de salida.
La función del desencadenador HTTP de Azure recibe los datos provenientes
de múltiples fuentes y almacena los datos de perfil de usuario en una tabla de
almacenamiento llamada tblUserProfile. Seguiremos los requisitos previos
enumerados a continuación:

• Para esta tarea, utilizaremos el mismo desencadenador HTTP que creamos en


la tarea anterior.
• Utilizaremos el explorador de Azure Storage, una herramienta que nos
ayuda a trabajar con los datos almacenados en la cuenta de Azure Storage.
Puede descargarla desde http://storageexplorer.com/.
• Para obtener más información sobre cómo conectarse a la cuenta de
almacenamiento utilizando el explorador de Azure Storage, visite
https://docs.microsoft.com/azure/vs-azure-tools-storage-manage-
with-storage-explorer.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a la pestaña Integrate de la función de desencadenador HTTP


RegisterUser.
2. Haga clic en el botón New Output, seleccione Azure Table Storage y luego
haga clic en el botón Select:

[9]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

3. Se le pedirá que instale los enlaces. Para ello, haga clic en Install y espere
unos minutos. Cuando los enlaces se hayan instalado, elija la siguiente
configuración de los enlaces de salida de Almacenamiento de tablas de
Azure:
°° Table parameter name: Este es el nombre del parámetro que utilizará
en el método Run de la función de Azure. Para este ejemplo, utilice el
valor objUserProfileTable.
°° Table name: Se creará una nueva tabla en el Almacenamiento de
tablas de Azure para conservar los datos. Si la tabla aún no existe,
Azure la creará automáticamente para usted. Para este ejemplo,
ingrese tblUserProfile como nombre de tabla.
°° Storage account connection: Si no aparece la cadena de conexión de
la cuenta de Storage, haga clic en new (como se muestra en la captura
de pantalla a continuación) para crear una nueva o elegir una cuenta
de almacenamiento existente.
°° Los enlaces de salida de Almacenamiento de tablas de Azure deben
ser como los que se muestran en la siguiente captura de pantalla:

4. Haga clic en Save para guardar los cambios.


5. Navegue hasta el editor de código haciendo clic en el nombre de la función y
pegue el código a continuación. Este código acepta la entrada que el usuario
final brindó 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 ]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

6. Para ejecutar la función, haga clic en el botón Run de la pestaña Test, con lo
cual se transfieren los parámetros firstname y lastname en Request body:

7. Si el procedimiento se realizó de manera correcta, debe aparecer el mensaje


Status 200 OK en la casilla Output, como se muestra en la captura de
pantalla anterior. Vayamos al explorador de Azure Storage para consultar el
almacenamiento de tablas y ver si la tabla llamada tblUserProfile se creó
correctamente:

[ 12 ]
Capítulo 1

Funcionamiento...
Azure Functions nos permite integrarnos fácilmente con otros servicios de Azure,
tan solo agregando un enlace de salida al desencadenador. En este ejemplo,
integramos el desencadenador HTTP con el enlace de tabla de Azure Storage y
también configuramos la cuenta de Azure Storage. Para ello, ingresamos la cadena
de conexión de almacenamiento y el nombre de la tabla de Azure Storage en la que
queremos crear un registro de cada una de las solicitudes de HTTP recibidas por el
desencadenador HTTP.

Asimismo, añadimos otro parámetro para administrar 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 utilizando
objUserProfileTable.

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


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

También creamos un objeto UserProfile, lo completamos con los valores recibidos


en el objeto de solicitud y luego lo transferimos a una operación de tabla.

Si desea conocer más información sobre cómo administrar las


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

[ 13 ]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

Comprender la conexión de almacenamiento


Al crear una nueva conexión de almacenamiento (consulte el paso 3 de la sección
Procedimiento de esta tarea), también se creará una nueva entrada en App settings:

Para desplazarse a la entrada App settings, haga clic en el menú Application


settings ubicado en la sección GENERAL SETTINGS de la pestaña Platform
features:

[ 14 ]
Capítulo 1

¿Qué es el servicio de Almacenamiento de tablas


de Azure?
El servicio de Almacenamiento de tablas de Azure es un medio persistente de clave/
valor NoSQL que sirve para almacenar datos semiestructurados.

Puede obtener más información sobre este tema en https://azure.


microsoft.com/services/storage/tables/.

Clave de partición y clave de fila


La clave principal de la tabla de Almacenamiento de tablas de Azure tiene dos
partes:

• Clave de partición: Los registros de almacenamiento de tablas de Azure


están clasificados y organizados en particiones. Cada registro ubicado en una
partición posee la misma clave de partición (p1 en nuestro ejemplo).
• Clave de fila: Es un valor único que se asigna a cada una de las filas.

Aún hay más...


Estas son las primeras líneas del código de esta tarea:
#r "Newtonsoft.json"
#r "Microsoft.WindowsAzure.Storage"

Estas líneas del código indican la función de tiempo de ejecución para incluir una
referencia a la biblioteca especificada en el contexto actual.

Guardado de imágenes de perfil en colas


utilizando enlaces de salida de cola
En la tarea anterior, aprendió a recibir dos parámetros de cadena, firstname
y lastname, en Request body y a almacenarlos en el Almacenamiento de
tablas de Azure. En esta tarea, vamos a añadir un nuevo parámetro llamado
ProfilePicUrl para la imagen de perfil del usuario a la que se puede acceder
públicamente a través de Internet. Aprenderá a recibir la URL de una imagen
y a guardarla en el contenedor de blobs de una cuenta de Azure Storage.

[ 15 ]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

Cualquiera pensaría que el parámetro de entrada ProfilePicUrl se podría haber


utilizado para descargar la imagen desde Internet en la tarea anterior, Mantenimiento
de datos de los empleados utilizando enlaces de salida de tablas de Azure Storage. No lo
hicimos porque el tamaño de las imágenes de perfil suele ser enorme con la tecnología
moderna y, por lo tanto, procesar las imágenes sobre la marcha en las solicitudes de
HTTP podría obstaculizar el rendimiento de la aplicación en general. Por ese motivo,
simplemente tomaremos la URL de la imagen de perfil, la almacenaremos en Queue
y, más adelante, podemos procesar la imagen y almacenarla en el blob.

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

Procedimiento...
Lleve a cabo los pasos siguientes:
1. Diríjase a la pestaña Integrate de la función de desencadenador HTTP
RegisterUser.
2. Haga clic en el botón New Output, seleccione Azure Queue Storage y luego
haga clic en el botón Select.
3. Proporcione los siguientes parámetros en la configuración de Azure Queue
Storage output:
° Message parameter name: Ingrese el nombre del parámetro
objUserProfileQueueItem, que se utilizará en el método Run
° Queue name: Ingrese el valor del nombre de cola
userprofileimagesqueue
° Storage account connection: Asegúrese de elegir la cuenta de
almacenamiento correcta en el campo Storage account connection
4. Haga clic en Save para crear el nuevo enlace de salida.
5. Vuelva al editor de código haciendo clic en el nombre de la función
(RegisterUser en este ejemplo) o en el archivo run.csx e incorpore los
cambios marcados en negrita en el siguiente código:
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, agregamos enlaces de salida de cola al añadir el


parámetro IAsyncCollecter al método Run y pasar el mensaje necesario
al método AddAsync. Los enlaces de salida guardarán ProfilePicUrl en
Queue. Ahora haga clic en Save para guardar los cambios de código en el
editor de código del archivo run.csx.
7. Vamos a probar el código añadiendo otro parámetro, ProfilePicUrl, en
Request body, y luego haga clic en el botón Run en la pestaña Test de la
ventana del editor de código de Azure Function. Es posible que la imagen
utilizada en el JSON a continuación ya no exista cuando lea este libro. Por lo
tanto, asegúrese 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á el mensaje Status: 200 OK, lo cual indica que la URL
de la imagen que pasó como parámetro de entrada en Request body se
creará como un mensaje de cola en el servicio de cola de Azure Storage.
Vayamos al explorador de Azure Storage para ver la cola denominada
userprofileimagesqueue, que es el nombre de cola que ingresamos en el
Paso 3. A continuación se muestra una captura de pantalla del mensaje de
cola que se creó:

[ 17 ]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

Funcionamiento...
En esta tarea, agregamos el enlace de salida para el mensaje de cola y realizamos los
siguientes cambios en el código:

• Agregamos un nuevo parámetro denominado out string


objUserProfileQueueItem, que sirve para enlazar la URL de la imagen de
perfil como contenido del mensaje de cola
• Usamos el método AddAsync de IAsyncCollector para el método Run que
permite guardar la URL de imagen en cola como mensaje de cola.

Almacenamiento de la imagen en el
Almacenamiento de blobs de Azure
En la tarea anterior, almacenamos la URL de la imagen en el mensaje de cola. Ahora
veamos cómo desencadenar 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 cola es la dirección URL de la imagen de perfil de un usuario, que se
procesará mediante Azure Functions y se almacenará como blob en el servicio de
blob de Azure Storage.

Preparación
En la tarea anterior, aprendimos a crear enlaces de salida de cola. En esta tarea,
vamos a tomar la URL de la cola para crear una matriz de bytes y luego escribirla en
un blob.

Esta tarea es la continuación de las tareas anteriores. Asegúrese de haberlas


implementado.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Para crear una nueva función de Azure, elija Azure Queue Storage Trigger
en las plantillas.
2. Después de elegir la plantilla, brinde estos detalles:
° Name your function: Asigne un nombre significativo, como
CreateProfilePictures.

[ 18 ]
Capítulo 1

° Queue name: el nombre de la cola es userprofileimagesqueue.


Estará controlado por la función de Azure. En la tarea anterior,
creamos un nuevo elemento para cada solicitud válida que ingresaba
al desencadenador HTTP (denominado RegisterUser) en la cola
userprofileimagesqueue. Para cada entrada nueva de un mensaje
de cola en el almacenamiento de esta cola, el desencadenador
CreateProfilePictures se ejecutará de forma automática.
° Storage account connection: Conexión de la cuenta de
almacenamiento donde se encuentran las colas.

3. Revise todos los detalles y haga clic en Create para crear una función nueva.
4. Desplácese hasta la pestaña Integrate, haga clic en New Output, elija la
opción Azure Blob Storage y luego haga clic en el botón Select.
5. En la sección Azure Blob Storage output, ingrese lo siguiente:
° Blob parameter name: Configúrelo en outputBlob
° Path: Indique userprofileimagecontainer/{rand-guid}
° Storage account connection: Elija la cuenta de almacenamiento
donde desea guardar los blobs y haga clic en el botón Save:

6. Haga clic en el botón Save para guardar todos los cambios.


7. Reemplace el código predeterminado del archivo run.csx de la función
CreateProfilePictures por el código a continuación. Este código toma la
dirección URL de la cola, crea una matriz de bytes y 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 ]
Desarrollo de aplicaciones en la nube utilizando desencadenadores de funciones y enlaces

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

8. Haga clic en el botón Save para guardar los cambios. Compruebe que no
haya errores de compilación en la ventana Logs:

9. Vamos a regresar a la función RegisterUser para probarla. Para ello,


tenemos que completar los campos firstname, lastname y ProfilePicUrl,
como hicimos en la tarea Guardado de imágenes de perfil en colas utilizando
enlaces de salida de cola.
10. Navegue hasta el explorador de Azure Storage y observe el contenedor
de blobs userprofileimagecontainer. Allí verá un nuevo blob:

11. Puede ver la imagen desde cualquier herramienta (como MS Paint o Internet
Explorer).

Funcionamiento...
Hemos creado un desencadenador de cola que se ejecuta como nuevo mensaje
y cuando llega un nuevo mensaje a la cola. Una vez que encuentra un nuevo mensaje
de cola, lo lee y, como sabemos, el mensaje es una URL de una imagen de perfil. La
función se encarga de realizar una solicitud de cliente web, de descargar los datos
de imagen en forma de una matriz de bytes y de escribir los datos en el blob que está
configurado como un blob de salida.

[ 20 ]
Capítulo 1

Aún hay más...


El parámetro rand-guid genera un nuevo GUID y se asigna al blob que se crea cada
vez que se activa el desencadenador.

Es obligación especificar el nombre del contenedor de blobs en el


parámetro Path del enlace de salida de almacenamiento de blobs al
configurar la salida de almacenamiento de blobs. De todos modos, si no
existe ningún nombre, Azure Functions lo crea automáticamente.
Puede utilizar mensajes de cola solo cuando desee almacenar mensajes de
hasta 64 KB. Si desea almacenar mensajes de más de 64 KB, debe utilizar
Azure Service Bus.

[ 21 ]
Trabajar con notificaciones
utilizando los servicios
SendGrid y Twilio
En este capítulo, trataremos los siguientes temas:

• Envío de una notificación por correo electrónico al administrador de un sitio


web utilizando el servicio SendGrid
• Envío de una notificación por correo electrónico de manera dinámica al
usuario final
• Implementación del registro de correo electrónico en el Almacenamiento
de blobs de Azure
• Modificación del contenido de un correo electrónico para incluir un
archivo adjunto
• Envío de una notificación por SMS al usuario final utilizando el servicio Twilio

Introducción
Para que todas las aplicaciones empresariales ejecuten sin problemas las operaciones
empresariales, es fundamental disponer de un sistema de comunicación confiable
entre el negocio y sus clientes. El canal de comunicación puede ser bidireccional y
enviarles un mensaje a los administradores encargados de la aplicación o alertas a los
clientes a través de correos electrónicos o SMS.

Azure se puede integrar con dos servicios de comunicación populares: SendGrid, para
correos electrónicos, y Twilio, para trabajar con SMS. En este capítulo, utilizaremos
ambos servicios de comunicación con el fin de aprender a aprovechar sus servicios
básicos para enviar mensajes entre los administradores del negocio y los usuarios finales.

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

A continuación encontrará la arquitectura que vamos a implementar para utilizar


los enlaces de salida de SendGrid y Twilio con un desencadenador HTTP y un
desencadenador de cola.

Envío de una notificación por correo


electrónico al administrador de un sitio
web utilizando el servicio SendGrid
En esta tarea, aprenderá a crear un enlace de salida para SendGrid y a enviar una
notificación por correo electrónico, con contenido estático, al administrador del sitio
web. En este caso de uso solo hay un administrador, por lo que codificaremos su
dirección de correo electrónico en el campo To address del enlace SendGrid output
(message).

Preparación
Antes de pasar a la siguiente sección, llevaremos a cabo los pasos siguientes:

1. Crear una clave de API para 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 Functions

Crear una cuenta de SendGrid


Lleve a cabo los pasos siguientes:

1. Diríjase al portal de administración de Azure y cree una cuenta SendGrid


Email Delivery. Para ello, búsquela en Marketplace, como se muestra en
la siguiente captura de pantalla:
[ 24 ]
Capítulo 2

2. En la hoja SendGrid Email Delivery, haga clic en el botón Create para


dirigirse a Create a New SendGrid Account. Seleccione free en las opciones
de Pricing tier, indique los detalles adicionales y haga clic en el botón Create,
como se muestra en la siguiente captura de pantalla:

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

En el momento de redactar, la cuenta gratuita de SendGrid


nos permite enviar 25 000 correos electrónicos sin cargo al mes.
Si desea enviar más correos electrónicos, puede obtener una
cuenta de nivel Silver S2, donde podrá enviar 100 000 correos
electrónicos mensuales.

3. Una vez que la cuenta se haya creado correctamente, diríjase a SendGrid


Accounts. Puede utilizar el cuadro de búsqueda en la parte superior,
como aparece en la siguiente captura de pantalla:

4. Desplácese hasta Settings, elija la opción Configurations y obtenga los


parámetros USERNAME y SMTP SERVER de la hoja Configurations,
como se ve en esta captura de pantalla:

[ 26 ]
Capítulo 2

Generar una clave de API desde el portal de


SendGrid
Lleve a cabo los pasos siguientes:

1. Para poder utilizar la cuenta de SendGrid en el tiempo de ejecución de las


funciones de Azure, es necesario proporcionar la clave de API de SendGrid
como entrada para Azure Functions. Puede generar una clave de API desde
el portal de SendGrid. Para navegar al portal de SendGrid, haga clic en el
botón Manage en la hoja Essentials de SendGrid Account, como se muestra
en la siguiente captura de pantalla:

2. En el portal de SendGrid, haga clic en API Keys debajo de la sección Settings


del menú ubicado a la izquierda, como se muestra en esta captura de pantalla:

3. En la página API Keys, haga clic en Create API Key, como se muestra en la
siguiente captura de pantalla:

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

4. En el elemento emergente Create API Key, ingrese un nombre y seleccione la


opción API Key Permissions. Luego, haga clic en el botón Create & View.
5. Espere un momento y verá la clave de API. Haga clic en la llave para copiar la
clave en el portapapeles, como se muestra en la siguiente captura de pantalla:

Configurar la clave de API de SendGrid con la


aplicación Azure Functions
Lleve a cabo los pasos siguientes:
1. Cree una nueva configuración para App settings en la aplicación Azure
Functions. Para ello, navegue hasta la hoja Application settings ubicada
debajo de la sección Platform features de la aplicación de funciones, como se
muestra en la siguiente captura de pantalla:

2. Haga clic en el botón Save después de añadir la configuración de App


settings del paso anterior.

Procedimiento...
En esta sección, realizaremos lo siguiente:
1. Crear un enlace de cola de almacenamiento para el desencadenador HTTP.
2. Crear un desencadenador de cola para procesar el mensaje del
desencadenador HTTP.
3. Crear un enlace de salida de SendGrid para el desencadenador de cola.
4. Crear un enlace de salida de Twilio para el desencadenador de cola.
[ 28 ]
Capítulo 2

Crear un enlace de cola de almacenamiento para


el desencadenador HTTP
Lleve a cabo los pasos siguientes:

1. Navegue hasta la pestaña Integrate de la función RegisterUser y haga clic


en el botón New Output para agregar un nuevo enlace de salida.
2. Elija la opción Azure Queue Storage y haga clic en el botón Select
para añadir el enlace e ingresar los valores que se muestran más abajo.
Luego, haga clic en el botón Save. Cree el nombre de la cola (en este
caso notificationqueue) que utilizaremos más adelante.

3. Desplácese hasta el método Run de la función RegisterUser y realice


los cambios resaltados abajo. Agregamos otro enlace de salida de cola y un
mensaje vacío para desencadenar la función de desencadenador de cola. Hasta
ahora, no agregamos ningún mensaje a la cola. Modificaremos el método
NotificationQueueItem.AddAsync(""); en la próxima tarea 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 utilizando los servicios SendGrid y Twilio

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

Crear un desencadenador de cola para procesar el


mensaje del desencadenador HTTP
1. Cree un desencadenador de Azure Queue Storage. Para hacerlo, elija la
plantilla que se muestra a continuación.

2. En el próximo paso, ingrese el nombre completo del desencadenador de cola


y el nombre de la cola que debe supervisar para enviar las notificaciones.
Después de brindar todos los detalles, haga clic en el botón Create para crear
la función.

[ 30 ]
Capítulo 2

3. Ahora que ya creamos la función de desencadenador de cola, vamos


a ejecutar la función RegisterUser para comprobar si se invoca al
desencadenador de cola. Abra la función RegisterUser en una pestaña
nueva y pruébela haciendo clic en el botón Run. En la ventana Logs de la
pestaña SendNotifications, se debe mostrar lo siguiente:

Una vez que comprobamos que el desencadenador de cola funciona correctamente,


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

Crear un enlace de salida de SendGrid para el


desencadenador de cola
1. Diríjase a la pestaña Integrate de la función SendNotifications y haga clic en
el botón New Output para agregar un nuevo enlace de salida.
2. Elija el enlace SendGrid y haga clic en el botón Select para agregar el enlace.
3. El próximo paso es instalar las extensiones SendGrid. Haga clic en el botón
Install para instalar las extensiones. Esto puede tardar unos minutos.
4. Brinde los siguientes parámetros en el enlace SendGrid output (message):

° Message parameter name: Utilice el valor predeterminado, que es


message. Vamos a utilizar este parámetro en el método Run más
adelante.
° SendGrid API Key: Elija la clave App settings que creó en
Application settings para almacenar la clave de API de SendGrid.
° To address: Ingrese la dirección de correo electrónico del
administrador.
° From address: Ingrese la dirección de correo electrónico desde
la cual desea enviar el correo electrónico. Por ejemplo,
donotreply@example.com.

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

° Message subject: Ingrese el asunto del correo electrónico que


quiere mostrar.
° Message Text: Ingrese el texto del cuerpo del correo electrónico.

5. Así debe verse el enlace SendGrid output (message) después de completar


todos los campos:

6. Una vez que revise los valores, haga clic en Save para guardar los cambios.
7. Navegue hasta el método Run de las funciones SendNotifications para
incorporar los siguientes cambios:
° Agregue una nueva referencia para SendGrid, junto con el espacio
de nombres SendGrid.Helpers.Mail.
° Agregue un nuevo mensaje de parámetro de salida del tipo
SendGridMessage.
° Cree un objeto del tipo SendGridMessage. Veremos cómo
utilizar este objeto en la siguiente tarea.

8. A continuación, se incluye 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 probaremos la funcionalidad de enviar el correo electrónico


navegando 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"
}

Funcionamiento...
El objetivo de esta tarea es enviar una notificación por correo electrónico al
administrador para informarle que se creó un nuevo registro de manera correcta.

Para enviar los correos electrónicos, utilizamos uno de los enlaces de salida de Azure
Functions, denominado SendGrid, como servidor de Simple Mail Transfer Protocol
(SMTP). Para ello, codificamos las siguientes propiedades en los enlaces SendGrid
output (message):

• La dirección desde la que se envía el correo electrónico ("from").


• La dirección a la que se envía el correo electrónico ("to").
• El asunto del correo electrónico.
• El cuerpo del correo electrónico.

Para enviar correos electrónicos, los enlaces de SendGrid output (message)


emplearán la clave de API indicada en App settings para invocar las API necesarias
de la biblioteca SendGrid.

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

Aún hay más...


Mientras se añaden los enlaces de SendGrid, se le pedirá que instale las extensiones
como se muestra a continuación:

Si no aparecen, elimine el enlace de salida y vuelva a crearlo. También puede


instalar las extensiones de forma manual siguiendo las instrucciones especificadas
en el artículo ubicado en https://docs.microsoft.com/azure/azure-functions/
install-update-binding-extensions-manual.

Envío de una notificación por correo


electrónico de manera dinámica al
usuario final
En la tarea anterior, codificamos la mayoría de los atributos relacionados con la
acción de enviar un correo electrónico a un administrador, ya que había un solo
administrador. En esta tarea, modificaremos la tarea anterior para enviar un correo
electrónico que diga Thank you for registration ("Gracias por registrarse")
a todos los usuarios.

Preparación
Asegúrese de que los siguientes parámetros están configurados correctamente:

• Se creó la cuenta de SendGrid y se generó una clave de API en el portal


de SendGrid.
• Se creó una configuración para App settings en el parámetro Application
settings de la aplicación de función.
• Se configuró la clave para App settings en los enlaces de SendGrid output
(message).
[ 34 ]
Capítulo 2

Procedimiento...
En esta tarea, actualizaremos el código que se encuentra en el archivo run.csx de las
siguientes funciones de Azure
• RegisterUser
• SendNotifications

Aceptar el nuevo parámetro de correo electrónico


en la función RegisterUser
Lleve a cabo los pasos siguientes:

1. Navegue hasta la función RegisterUser, en el archivo run.csx, y agregue


una nueva variante de cadena que acepte un nuevo parámetro de entrada,
llamado email, desde el objeto request, como se detalla más abajo. Tenga
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. Actualice el siguiente código resaltado a la clase UserProfile y haga clic en


el botón Save 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 utilizando los servicios SendGrid y Twilio

public string Email { get; set; }


}

Recuperar la información de UserProfile en el


desencadenador SendNotifications
Lleve a cabo los pasos siguientes:

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


agregue la referencia NewtonSoft.Json y el espacio de nombres.
2. El desencadenador de cola recibirá la entrada en forma de cadena JSON.
Recurriremos al método JsonConvert.Deserializeobject para convertir
la cadena en un objeto dinámico y recuperar las propiedades individuales.
Reemplace el código actual por el siguiente código, donde completamos de
forma dinámica las propiedades de SendGridMessage del 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 prueba, como se muestra aquí:
{
"firstname": "Praveen",
"lastname": "Sreeram",
"email":"example@gmail.com",
"ProfilePicUrl":"A Valid url here"
}

4. Esta es la captura de pantalla del correo que recibí:

Funcionamiento...
Actualizamos el código de la función RegisterUser para aceptar otro parámetro
nuevo llamado email.

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


utilizando la API de SendGrid. También configuramos el resto de los parámetros,
como la dirección desde la que se envía el mensaje (From), el asunto del mensaje
(Subject) y el contenido del mensaje en el código, para personalizarlo de manera
dinámica a partir de los requisitos.

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

Asimismo, podemos borrar los campos en los enlaces de SendGrid output, como se
detalla en esta captura de pantalla:

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


sobre los valores especificados en el paso anterior.

Aún hay más...


También puede enviar contenido HTML en el cuerpo del correo electrónico para que
luzca más atractivo. A continuación, se detalla un simple ejemplo, donde solamente
apliqué la etiqueta de negrita (<b>) al nombre del usuario final:
message.AddContent("text/html", "Thank you <b>" + FirstName + "</b><b>
" + LastName +" </b>so much for getting registered to our site.");

Esta es la captura de pantalla del correo electrónico, con mi nombre en negrita:

[ 38 ]
Capítulo 2

Implementación del registro de correo


electrónico en el Almacenamiento
de blobs de Azure
La mayoría de las aplicaciones empresariales de correos electrónicos automatizados
sirven para enviar correos electrónicos con notificaciones, alertas, etcétera, al usuario
final. A veces, los usuarios se quejan de que no recibieron ningún correo electrónico,
aunque no veamos ningún error en la aplicación al enviar dichas alertas de notificación.
Pueden existir muchas razones por las que los usuarios no recibieron el correo
electrónico. Cada proveedor de servicios de correo electrónico posee diferentes filtros
contra correos no deseados que pueden bloquear los correos electrónicos en la bandeja
de entrada del usuario final. Sin embargo, estos correos electrónicos pueden contener
información importante para los usuarios. Se recomienda almacenar el contenido de
todos los correos electrónicos que se envían a los usuarios finales para que podamos
recuperar la información en una etapa posterior y solucionar problemas imprevistos.
En esta tarea, aprenderá a crear un nuevo archivo de registro de correo electrónico con
la extensión .log para cada registro nuevo. Este archivo de registro se puede utilizar
como redundancia para los datos guardados en el almacenamiento de tablas También
aprenderá a almacenar los archivos de registro de correo electrónico como blob en un
contenedor de almacenamiento, junto con los datos proporcionados por el usuario
final durante el registro.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a la pestaña Integrate de la función SendNotifications, haga clic


en New Output y elija Azure Blob Storage. El sistema le pedirá que instale
las extensiones de almacenamiento. Hágalo para continuar.
2. Proporcione los parámetros necesarios en la sección de salida Azure Blob
Storage, como se muestra en la siguiente captura de pantalla. Compruebe
que figure la extensión .log en el campo Path:

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

3. Desplácese hasta el editor de código del archivo run.csx de la función


SendNotifications y realice estos cambios:
1. Agregue el nuevo parámetro outputBlob de tipo TextWriter al
método Run.
2. Añada una nueva variable de cadena denominada emailContent.
Esta variable sirve para enmarcar el contenido del correo electrónico.
Utilizamos la misma variable para crear el contenido del archivo de
registro que finalmente se almacena en el blob.
3. Enmarque el contenido del correo electrónico anexando el texto
estático necesario y los parámetros de entrada recibidos en Request
body, como se muestra aquí:
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. Ejecute una prueba con la misma carga de solicitud que utilizamos en la tarea
anterior.
5. Después de la prueba, se creará el archivo de registro en el contenedor, que
tendrá el nombre userregistrationemaillogs:

[ 40 ]
Capítulo 2

Funcionamiento...
Acabamos de crear nuevos enlaces de salida de blob de Azure. Apenas recibamos
una nueva solicitud, se creará el contenido del correo electrónico y se escribirá en
un nuevo archivo .log (también puede utilizar otra extensión), que será almacenado
como blob en el contenedor especificado en el campo Path de los enlaces de salida.

Modificación del contenido de un correo


electrónico para incluir un archivo
adjunto
En esta tarea, aprenderá a enviar un archivo como adjunto al usuario registrado. En
la tarea anterior, creamos un archivo de registro del contenido de correo electrónico.
Enviaremos el mismo archivo como adjunto al correo electrónico. Sin embargo, en
las aplicaciones reales, no es necesario que envíe archivos de registro al usuario final.
Para hacerlo más simple, enviaremos el archivo de registro como archivo adjunto.

En el momento de escribir, SendGrid recomienda que el


tamaño de los datos adjuntos no supere los 10 MB, aunque
técnicamente, el correo electrónico puede ser de hasta 20 MB.

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

Preparación
Esta tarea es la continuación de la tarea anterior. Si está leyendo esto, primero
asegúrese de repasar las tareas anteriores de este capítulo.

Procedimiento...
Tendremos que seguir estos pasos antes de avanzar a la próxima sección:

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


RowKey de la tabla. Lo haremos utilizando la interfaz IBinder.
2. Envíe este archivo como archivo adjunto al correo electrónico.

Personalizar el nombre del archivo de registro


a través de la interfaz IBinder
Lleve a cabo los pasos siguientes:

1. Desplácese hasta el archivo run.csx de la función SendNotifications.


2. Elimine el objeto TextWriter y reemplácelo por el enlazador de variable del
tipo IBinder. A continuación, se incluye 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. Debido a que eliminamos el objeto TextWriter, la función outputBlob.


WriteLine(emailContent); dejará de funcionar. Lo sustituiremos 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 utilizamos en las
tareas anteriores.
5. Como figura en la captura de pantalla más abajo, se puede ver el nuevo
archivo de registro de correo electrónico creado utilizando el elemento
RowKey del nuevo registro guardado en el Almacenamiento de tablas
de Azure:

Agregar un archivo adjunto al correo electrónico


Lleve a cabo los pasos siguientes:

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


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

2. Ejecute una prueba con la misma carga de solicitud que empleó en las tareas
anteriores.

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

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


archivo adjunto:

Si desea obtener más información sobre la API de SendGrid, visite


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

Envío de una notificación por SMS al


usuario final utilizando el servicio Twilio
En la mayoría de las tareas anteriores de este capítulo, trabajamos con
desencadenadores de SendGrid para enviar correos electrónicos en diferentes
escenarios. En esta tarea, aprenderá a enviar notificaciones a través de SMS,
utilizando una de las principales plataformas de comunicación en la nube,
llamada Twilio.

Puede obtener más información sobre Twilio en


https://www.twilio.com/.

[ 44 ]
Capítulo 2

Preparación
Para utilizar 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 crear la cuenta, tome los elementos ACCOUNT SID y AUTH
TOKEN del Dashboard de Twilio, como se muestra a continuación.
Crearemos dos App settings en la hoja Application settings de la aplicación
de función para estas dos configuraciones:

3. Para empezar a enviar mensajes, es necesario crear un número activo en


Twilio, que se empleará como el número desde el que se enviarán los SMS,
denominado From number. Puede crear y administrar números en el Phone
Numbers Dashboard. Visite https://www.twilio.com/console/phone-
numbers/incoming y haga clic en el botón Get Started, como se muestra en
la siguiente captura de pantalla:

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

4. En la página Get Started with Phone Numbers, haga clic en Get your first
Twilio phone number, como vemos aquí:

5. Una vez que obtenga su número, aparecerá de este modo:

6. El último paso es verificar el número al que desea enviar un SMS. Solo puede
tener un número en la cuenta de prueba. Para verificar un número, visite la
página Twilio's Verified disponible en https://www.twilio.com/console/
phone-numbers/verified. La siguiente es una captura de pantalla de la lista
de números verificados:

[ 46 ]
Capítulo 2

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a la hoja Application settings de la aplicación de función y agregue


dos claves para almacenar TwilioAccountSID y TwilioAuthToken, de la
siguiente manera:

2. Diríjase a la pestaña Integrate de la función SendNotifications, haga clic en


New Output y elija Twilio SMS.
3. Haga clic en Select e ingrese los siguientes valores en los enlaces de Twilio
SMS output. Instale las extensiones de Twilio. El elemento From number
se genera en el portal de Twilio, que abordamos en la sección Preparación
de esta tarea:

4. Desplácese hasta el editor de código y agregue las siguientes líneas de


código, resaltadas en negrita. En el código anterior, codifiqué el parámetro
To number. Sin embargo, en escenarios reales, recibirá el número móvil del
usuario final de manera dinámica y enviará 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 utilizando 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 realice una ejecución de prueba en la función RegisterUser con la


misma carga de solicitud.
6. Esta es la captura de pantalla del SMS que recibí:

[ 48 ]
Capítulo 2

Funcionamiento...
Creamos una nueva cuenta de Twilio y copiamos la clave de la aplicación y la
ID de la cuenta en la App settings de la aplicación Azure Functions. El tiempo
de ejecución de la aplicación de función empleará estas dos configuraciones para
conectarse con la API de Twilio y enviar el SMS.

Para hacerlo más simple, codifiqué el número de teléfono en los enlaces de salida.
No obstante, en las aplicaciones reales, se envía el SMS al número de teléfono
indicado por los usuarios finales.

Puede reproducir el video https://www.youtube.com/watch?v=ndxQXnoDIj8


para ver una implementación en curso.

[ 49 ]
Integración perfecta de Azure
Functions con los servicios
de Azure
En este capítulo, trataremos los siguientes temas:

• Uso de Cognitive Services para ubicar rostros en imágenes.


• Interacciones de Azure SQL Database con Azure Functions.
• Supervisión de tweets utilizando Logic Apps y notificar a los usuarios
cuando un usuario popular publica en esta red social.
• Integración de Logic Apps con funciones sin servidor.
• Auditoría de datos de Cosmos DB utilizando desencadenadores de fuente
de cambios.

Introducción
Uno de los principales objetivos de Azure Functions es permitir que los
desarrolladores se centren exclusivamente en desarrollar los requisitos y la lógica
de las aplicaciones, y abstraer todo lo demás.

Como desarrollador o usuario de negocios, no puede permitirse inventar


y desarrollar sus propias aplicaciones desde cero para cada una de sus necesidades
empresariales. Primero tendría que investigar los sistemas existentes y ver si se
ajustan a sus requisitos empresariales. Asimismo, no sería fácil entender las API
de los demás sistemas e integrarlas, ya que fueron desarrolladas por otra persona.

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

Azure le proporciona muchos conectores que puede aprovechar para integrar sus
aplicaciones empresariales con otros sistemas de una manera bastante sencilla.

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


disponibles en el ecosistema de Azure.

Uso de Cognitive Services para ubicar


rostros en imágenes
En esta tarea, aprenderá a utilizar la API de Computer Vision para detectar rostros
dentro de una imagen. Vamos a capturar las coordenadas de rostros para localizarlos
y guardarlos en diferentes áreas del almacenamiento de tablas de Azure basadas en
el género.

Preparación
Para empezar, necesitamos crear una API de Computer Vision y configurar sus
claves de API para que Azure Functions (o cualquier otro programa) acceda a ella
mediante programación.

Asegúrese de tener instalado el explorador de Azure Storage y de que esté


configurado para acceder al área de almacenamiento donde va a cargar los blobs.

Crear una nueva cuenta de Computer Vision API


Lleve a cabo los pasos siguientes:

1. Busque computer vision y haga clic en Create.


2. El siguiente paso es proporcionar todos los detalles para crear una cuenta
de Computer Vision API. En el momento en que escribimos esto, Computer
Vision API tiene solo dos niveles de precios. Opté por la cuenta gratuita,
F0, que permite realizar 20 llamadas a API por minuto y tiene un límite de
5000 llamadas por mes.

[ 52 ]
Capítulo 3

Configurar la aplicación
Lleve a cabo los pasos siguientes:

1. Después de generar la cuenta de Computer Vision API, puede navegar hasta


la hoja Keys y tomar algunas de estas claves:

2. Desplácese hacia la aplicación Azure Functions, configure Application


settings con el nombre Vision_API_Subscription_Key y utilice alguna
de las claves anteriores como valor. El tiempo de ejecución de las funciones
de Azure utilizará esta clave para conectarse con la API de Cognitive Services
de Computer Vision y consumirla.
3. Tome nota de la ubicación en la que va a crear el servicio Computer
Service. En mi caso, elegí West Europe. Al pasar las imágenes a la API
de Cognitive Services, es importante comprobar que el punto de conexión
de la API comienza con el nombre de la ubicación. Sería algo así: https://
westeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visu
alFeatures=Faces&language=en.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva función empleando una de las plantillas predeterminadas


llamada Azure Blob Storage Trigger.

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

2. A continuación, brinde el nombre de la función de Azure junto con los


parámetros Path y Storage account connection. Cargaremos una imagen
en el contenedor Azure Blob Storage trigger (image) (mencionado en el
parámetro Path en la siguiente captura de pantalla) ubicado al final de esta
sección:

Observe que, al crear la función, la plantilla crea un enlace Blob Storage


Table output y nos permite indicar el nombre del parámetro Table name. Sin
embargo, no podemos asignar un nombre al parámetro mientras creamos la
función. Lo podremos cambiar una vez que lo hayamos creado. Después de
revisar todos los detalles, haga clic en el botón Create para crear la función
de Azure.
3. Una vez creada la función, desplácese a la pestaña Integrate, haga clic en
New Output y elija la opción Azure Table Storage. Luego haga clic en el
botón Select. Ingrese los valores de los parámetros y haga clic en el botón
Save, como se muestra en la siguiente captura de pantalla:

[ 54 ]
Capítulo 3

4. Ahora vamos a crear otro enlace Azure Table Storage output para almacenar
toda la información de mujeres. Para ello, haga clic en el botón New Output
en la pestaña Integrate, seleccione Azure Table Storage y haga clic en el
botón Select. Así debe verse después de proporcionar los valores de entrada:

5. Revise todos los detalles y haga clic en el botón Save para crear el enlace
Azure Table Storage output y almacenar la información sobre mujeres.

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

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


LocateMaleFemaleFaces y añada los parámetros outMaleTable
y outFemaleTable. El código a continuación toma la secuencia de imágenes
cargada en el blob, que luego se pasa como entrada a Cognitive Services
y este devuelve un JSON con toda la información de los rostros. Una vez
recibida la información de rostros, incluidas las coordenadas y los detalles
de género, almacenamos las coordenadas de rostros en el almacenamiento
de tabla respectivo utilizando los enlaces de salida de tabla:
#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. Agreguemos una condición (resaltada en negrita en el código mencionado en


el Paso 10) para comprobar el género y, en base a él, almacenar la información
en el almacenamiento de tabla correspondiente.
8. A partir del explorador de Azure Storage, cree un nuevo contenedor de blobs
denominado images, como se observa en la siguiente captura de pantalla:

9. Carguemos una imagen con rostros masculinos y femeninos en el contenedor


denominado images utilizando el explorador de Azure Storage, como se
muestra aquí:

[ 58 ]
Capítulo 3

10. La función se desencadena tan pronto como se carga la imagen. Este es el


JSON que se registró en la consola Logs 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 usted es un desarrollador de front-end con experiencia en HTML5


y en tecnologías relacionadas con Canvas, incluso puede dibujar
cuadrados que localicen los rostros en la imagen utilizando 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 creó dos tablas de Almacenamiento de tablas de Azure


diferentes, como se muestra aquí:

Funcionamiento...
Primero creamos un enlace de salida de Almacenamiento de tablas para almacenar
detalles sobre todos los hombres que aparecen en las fotos. Luego creamos otro
enlace de salida de Almacenamiento de tablas para almacenar los detalles sobre
todas las mujeres.

Aunque utilizamos el código predeterminado completo que proporciona la plantilla


de Azure Functions para almacenar todas las coordenadas de rostros en una sola
tabla, acabamos de realizar 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.

Tenga en cuenta que las API no son 100 % precisas a la hora de identificar
el género correcto. Por lo tanto, en sus entornos de producción, debe tener
un mecanismo de reserva para manejar tales situaciones.

Aún hay más...


El código predeterminado que brinda la plantilla invoca Computer Vision API
al pasar la imagen que cargamos en el almacenamiento de blobs. Las plantillas
de localización de rostros invocan la llamada API al pasar el parámetro
visualFeatures=Faces, que brinda información sobre lo siguiente:

• Edad
• Género
• Coordenadas de los rostros en la imagen

[ 60 ]
Capítulo 3

Puede obtener más información acerca de Computer Vision API en


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

Utilice 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 emplea la función para recuperar la clave, que es
fundamental para realizar una solicitud a Microsoft Cognitive Services.

Se recomienda almacenar todas las claves y la información confidencial en


la configuración de la aplicación.

ICollector y IAsyncCollector se utilizan para la inserción masiva


de datos.

Interacciones de Azure SQL Database


con Azure Functions
Hasta ahora, aprendió a almacenar datos en los 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 tarea, aprenderá a utilizar la API de ADO.NET para conectarse a una base
de datos SQL e insertar datos JSON en una tabla denominada EmployeeInfo.

Preparación
Diríjase al portal de Azure y haga lo siguiente:

1. Cree un SQL Server lógico con el nombre que prefiera. Se recomienda crearlo
en el mismo grupo de recursos donde tiene las funciones de Azure.
2. Cree una Azure SQL Database llamada Cookbookdatabase. Para ello,
elija Blank database en el menú desplegable Select source en la hoja SQL
Database mientras crea la base de datos.

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

3. Cree una regla de firewall para su dirección IP haciendo clic en el botón


Set Firewall rule en la hoja Overview para conectarse con las bases de
datos de Azure SQL a través de SQL Server Management Studio (SSMS).
Si no tiene SSMS, instale la versión más reciente. Puede descargarla desde
https://docs.microsoft.com/sql/ssms/download-sql-server-
management-studio-ssms.
4. Haga clic en el enlace Show database connection strings en la hoja
Essentials de SQL Database, como se muestra en la siguiente captura de
pantalla:

5. Copie la cadena de conexión de la hoja a continuación. Asegúrese de


reemplazar las plantillas your_username y your_password con su nombre
de usuario y contraseña reales:

[ 62 ]
Capítulo 3

6. Abra el SSMS y conéctese al servidor SQL Server lógico de Azure que creó en
los pasos anteriores.
7. Una vez que esté conectado, cree una nueva tabla llamada 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
)
)

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Navegue a la aplicación de función, cree un desencadenador HTTP nuevo


con la plantilla HttpTrigger-CSharp y elija la opción Authorization level
como Anonymous.
2. Desplácese hasta el editor de código de run.csx en la función
SaveJSONToAzureSQLDatabase y reemplace el código predeterminado por el
siguiente. Este código toma los datos que se pasan al desencadenador HTTP
y los inserta en la base de datos utilizando la API de 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.");

Recuerde validar todos los parámetros de entrada. Para hacerlo más simple, el código
que valida los parámetros de entrada no está incluido. Asegúrese de validar todos los
parámetros antes de guardarlos en su base de datos. También es recomendable almacenar la
cadena de conexión en Application settings.

3. Ejecutemos el desencadenador HTTP con los siguientes datos de prueba


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

Recuerde validar todos los parámetros de entrada. Para hacerlo más simple, el código
que valida los parámetros de entrada no está incluido. Asegúrese de validar todos los
parámetros antes de guardarlos en su base de datos.

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

4. Se insertó un registro correctamente, como se muestra en esta captura de


pantalla:

Funcionamiento...
El objetivo de esta tarea era aceptar los valores de entrada del usuario y guardarlos
en una base de datos relacional desde donde los datos se puedan recuperar más
tarde para fines operativos. Para ello, utilizamos Azure SQL Database, una oferta
de base de datos relacional también conocida como base de datos como servicio
(DBaaS). Hemos creado una nueva base de datos SQL y reglas de Firewall que nos
permiten conectarnos de forma remota desde la estación de trabajo de desarrollo
local utilizando SSMS. También creamos una tabla denominada EmployeeInfo, que
se puede utilizar para guardar datos.

Desarrollamos un programa sencillo empleando la API de ADO.NET que se conecta


con Azure SQL Database e inserta datos en la tabla EmployeeInfo.

Supervisión de tweets utilizando Logic


Apps y notificar a los usuarios cuando
un usuario popular publica en esta red
social
Uno de mis colegas, que trabaja para un proyecto de gestión de reclamos sociales,
se encarga de supervisar los problemas que los usuarios publican en las plataformas
de redes sociales, como Facebook, Twitter y demás. Se enfrentaba al problema de
supervisar continuamente los tweets publicados en el nombre de usuario de Twitter
de su cliente con hashtags específicos. Su trabajo principal era responder de
inmediato a los tweets de usuarios con una gran cantidad de seguidores, es decir,
usuarios con más de 50.000 seguidores. Por lo tanto, estaba buscando una solución
que supervisara un hashtag en particular y le avisara cada vez que un usuario
con más de 50.000 seguidores tuiteara para que su equipo pudiera responderle
rápidamente.
[ 66 ]
Capítulo 3

Tenga en cuenta que, para hacerlo más simple, trabajaremos con


200 seguidores en lugar de 50.000.

Antes de conocer Azure Logic Apps, pensaba que tardaría varias semanas en
aprender, desarrollar, probar e implementar una solución de este tipo. Obviamente,
se necesitaría una buena cantidad de tiempo para aprender, comprender y consumir
la API de Twitter (o cualquier otra red social) para obtener la información necesaria
y crear una solución completa que resolviera el problema.

Por fortuna, después de oír acerca de Logic Apps y sus innovadores conectores,
bastaron unos 10 minutos para diseñar una solución para el problema que tenía mi
amigo.

En esta tarea, aprenderá a diseñar una aplicación lógica que se integra con Twitter
(para supervisar tweets) y Gmail (para enviar correos electrónicos).

Preparación
Para trabajar con esta tarea, necesitamos lo siguiente:

• Una cuenta de Twitter válida.


• Una cuenta de Gmail válida.

Cuando trabajemos con esta tarea, tendremos que autorizar el acceso de Azure Logic
Apps a sus cuentas.

Procedimiento...
Llevaremos a cabo los pasos siguientes:

1. Crear una aplicación lógica nueva.


2. Diseñar la aplicación lógica con conectores de Twitter y Gmail.
3. Probar la aplicación lógica enviando los tweets con el hashtag específico.

Crear una aplicación lógica nueva


Lleve a cabo los pasos siguientes:

1. Inicie sesión en el portal de administración de Azure, busque logic apps


y seleccione Logic App.

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

2. En la hoja Create logic app, después de completar los campos Name,


Resource group, Subscription y Location, haga clic en el botón Create para
crear la aplicación lógica:

[ 68 ]
Capítulo 3

Diseñar la aplicación lógica con conectores


de Twitter y Gmail
Lleve a cabo los pasos siguientes:

1. Una vez creada la aplicación lógica, navegue hasta Logic app designer y elija
Blank logic app.
2. A continuación, se le pedirá que seleccione Connectors. En la lista
Connectors, haga clic en Twitter. El sistema le pedirá que se conecte
a Twitter, para lo cual tendrá que proporcionar las credenciales de su
cuenta de Twitter. Si ya se conectó, directamente aparecerá la lista de
desencadenadores en Triggers asociados con el conector de Twitter, como se
muestra en la siguiente captura de pantalla:

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


complete el campo Search text (para buscar, por ejemplo, hashtags y palabras
clave) y que especifique la frecuencia, en Frequency, a la cual desea que la
aplicación lógica sondee los tweets. Esto es lo que verá después de indicar los
detalles:

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

4. Agregaremos una nueva condición. Para ello, haga clic en Next Step, busque
condition y seleccione la acción Condition, como se muestra a continuación:

5. Luego de la instrucción anterior, aparecerá la siguiente pantalla donde podrá


elegir los valores de la condición y qué le gustaría añadir cuando la condición
evalúe según true (verdadero) o false (falso):

[ 70 ]
Capítulo 3

6. Al hacer clic en el campo de entrada Choose a value, verá todos los


parámetros en los que puede agregar una condición. En este caso, elija
Followers count, como se muestra en la siguiente captura de pantalla:

7. Después de elegir el parámetro Followers Count, se crea una condición


(Followers count is greater than or equal to 200), como apreciamos aquí:

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

8. En la sección If true de la condición anterior, busque la conexión de Gmail


y seleccione Gmail | Send email, como se ve aquí:

9. El sistema le pedirá que inicie sesión si aún no lo ha hecho. Proporcione sus


credenciales y autorice a Azure Logic Apps a acceder a su cuenta de Gmail.

[ 72 ]
Capítulo 3

10. Luego de haber dado la autorización, enmarque el correo electrónico con


Add dynamic content con los parámetros de Twitter, como se muestra en la
siguiente captura de pantalla: Si no ve el campo Followers count, haga clic en
el enlace Show more:

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


en el enlace Mostrar más.

11. Una vez que haya terminado, haga clic en el botón Save.

Probar la funcionalidad de la aplicación lógica


Lleve a cabo los pasos siguientes:

1. Vamos a publicar un tweet 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. Después de aproximadamente un minuto, se debe desencadenar la


aplicación lógica. Desplacémonos a la hoja Overview de la aplicación lógica
y observemos el parámetro Runs history:

3. ¡Sí! Efectivamente, se desencadenó dos veces y recibí los correos electrónicos.


En la siguiente captura de pantalla, se puede ver uno de ellos:

Funcionamiento...
Creó una nueva aplicación lógica y eligió 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 conteo de seguidores es
mayor o igual a 200. Si se cumple esta condición, se crea una nueva acción con un
nuevo conector de Gmail capaz de enviar un correo electrónico con el contenido
dinámico enmarcado utilizando los parámetros del conector de Twitter.

Integración de Logic Apps con funciones


sin servidor
En la tarea anterior, aprendió a integrar diferentes conectores utilizando Logic Apps.
En esta tarea, implementaremos la misma solución que en la tarea anterior. Para ello,
tan solo moveremos la lógica condicional que comprueba la cantidad de seguidores
a Azure Functions.

[ 74 ]
Capítulo 3

Preparación
Antes de continuar, llevaremos a cabo los pasos siguientes:

1. Cree una cuenta de SendGrid (si aún no la creó), tome la clave de la API de
SendGrid y cree una nueva clave en el campo Application settings de la
aplicación de función.
2. Instale Postman para probar el desencadenador HTTP. Puede descargar la
herramienta desde https://www.getpostman.com/.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Elija el desencadenador HTTP para crear una nueva función y asígnele el


nombre ValidateTwitterFollowerCount.
2. Navegue hasta la pestaña Integrate y agregue un nuevo enlace de salida,
SendGrid, haciendo clic en el botón New Output:

3. Reemplace el código predeterminado por el código siguiente y haga clic en


Save. Este código se encarga de verificar la cantidad de seguidores y, si es
superior a 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. Para probar la función con Postman, elija los parámetros resaltados en la


siguiente captura de pantalla. En los pasos siguientes, después de integrar la
función de Azure ValidateTwitterFollowerCount, el conector de Twitter
de la aplicación lógica publicará los demás parámetros de entrada, como
followersCount, tweettext y Name:

[ 76 ]
Capítulo 3

5. Cree una nueva aplicación lógica denominada


NotifywhenTweetedbyPopularUserUsingFunctions.
6. Comience a diseñar la aplicación con la plantilla Blank logic app, elija
el conector Twitter y configure los parámetros Search text, Frequency
e Interval.
7. Haga clic en New step para agregar una acción. En la sección Choose an
action, elija 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 detallarán todas las aplicaciones


de función de Azure disponibles, como vemos en la siguiente captura
de pantalla:

9. Haga clic en la aplicación de función donde creó la función


ValidateTwitterFollowerCount. Ahora seleccione la función
ValidateTwitterFollowerCount, como se ve en la siguiente captura
de pantalla:

[ 78 ]
Capítulo 3

10. En el próximo paso, prepare la entrada JSON que debe pasar desde
la aplicación lógica hasta la función de desencadenador HTTP
ValidateTwitterFollowerCount que desarrollamos. Vamos a enmarcar
la entrada JSON del mismo modo en que lo hicimos cuando probamos la
función del desencadenador HTTP utilizando Postman, como se muestra en
la siguiente captura de pantalla (la única diferencia es que los valores, como
followersCount, Name y tweettext ahora son dinámicos):

11. Después de revisar todos los parámetros necesarios para la función


ValidateTwitterFollowerCount, haga clic en el botón Save para guardar
los cambios.
12. Puede esperar unos minutos o publicar un tweet con el hashtag que
configuró en el campo de entrada Search text.

Aún hay más...


Si no ve el parámetro dinámico previsto, haga clic en el botón See more, 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,


codificamos el umbral de cantidad de seguidores en 200. Se recomienda
almacenar estos valores como elementos configurables. Para ello,
almacénelos en Application settings.

Consulte también
• Consulte la tarea Envío de una notificación por correo electrónico de manera
dinámica al usuario final en el Capítulo 2, Trabajar con notificaciones utilizando los
servicios SendGrid y Twilio

Auditoría de datos de Cosmos DB


utilizando desencadenadores de fuente
de cambios
Es posible que muchos de ustedes ya hayan oído hablar de Cosmos DB, ya que se
ha vuelto muy popular y muchas organizaciones lo están utilizando debido a las
funciones que proporciona.
En esta tarea, aprenderemos a integrar las funciones de Azure sin servidor con una
base de datos NoSQL en Cosmos DB. Puede obtener más información sobre Cosmos
DB en https://docs.microsoft.com/azure/cosmos-db/introduction.
A menudo, es necesario registrar los cambios de campos, atributos, documentos
y demás para fines de auditoría. En el mundo de las bases de datos relacionales,
es posible que haya visto que algunos desarrolladores utilizan desencadenadores
o procedimientos almacenados para implementar este tipo de funcionalidad de
auditoría, donde se escribe el código para almacenar datos en una tabla de auditoría
independiente.
En esta tarea, aprenderemos qué sencillo es lograr el caso de uso anterior y auditar
las colecciones de Cosmos DB. Para ello, escribiremos una función simple que se
desencadena siempre que hay un cambio en un documento de una colección de
Cosmos DB.

En lo que respecta a 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 empezar, primer tenemos que hacer lo siguiente:
• Crear una cuenta de Cosmos DB.
• Crear una nueva colección de Cosmos DB en la que pueda almacenar datos
en forma de documentos.
[ 80 ]
Capítulo 3

Crear una cuenta de Cosmos DB nueva


Diríjase al portal de Azure y cree una nueva cuenta de Cosmos DB. Deberá
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
<<accountname>>.document.azure.com.
• Una API configurada como SQL. Esto garantizará que pueda escribir
consultas en SQL. Puede probar cualquier otra API que desee.

Crear una colección de Cosmos DB nueva


Lleve a cabo los pasos siguientes:

1. Después de crear la cuenta, cree una nueva base de datos y una colección.
Podemos crear ambas en un solo paso directamente desde el portal.
2. Desplácese hasta la pestaña Overview y haga clic en el botón Add Collection
para crear una colección nueva:

3. El sistema lo llevará automáticamente a la pestaña Data Explorer, donde se le


pedirá que proporcione los siguientes detalles:
Nombre del
Valor Comentario
campo
ID de la base de Este es un contenedor de varias
cookbookdatabase
datos colecciones de Cosmos DB.
cookbookdata- Este es el nombre de la colección
ID de colección collection donde va a almacenar los datos.

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

Nombre del
Valor Comentario
campo
Según sus cargas de trabajo de
Capacidad de producción, es posible que tenga que
Fixed (10 GB)
almacenamiento trabajar con Unlimited, ya que, de lo
contrario, podría obtener particiones.
Esta es la capacidad de la colección
de Cosmos DB. El rendimiento
Rendimiento
de las lecturas y escrituras de la
(400-10.000 400
colección depende del rendimiento
RU/s)
que configure cuando aprovisione la
colección.

4. Luego haga clic en el botón OK para crear la colección. Si todo salió


correctamente, verá algo parecido a lo siguiente en la pestaña Data Explorer
de la cuenta de Cosmos DB:

Hemos creado con éxito 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 a desencadenarla siempre que haya un cambio en la colección de Cosmos DB.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Desplácese a la cuenta de Cosmos DB y haga clic en el menú Add Azure


Function en la hoja All settings de la cuenta de Cosmos DB.

[ 82 ]
Capítulo 3

2. El sistema lo dirigirá a la hoja Add Azure Function. Allí, elija la aplicación de


función de Azure donde desea crear la nueva función (Cosmos DB trigger)
que se desencadenará cada vez que ocurra un cambio en la colección.
Se verá así:

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

3. Una vez que haya repasado los detalles, haga clic en el botón Save
(que se muestra en la captura de pantalla anterior) para crear la
nueva función que se desencadenará con cada cambio en la colección.
Vayamos rápidamente a la aplicación de función de Azure (en mi caso
es AzureFunctionCookBookV2) para ver si se creó la nueva función
denominada cookbookdatacollectionTrigger. Así se ve mi aplicación de
función:

4. Reemplace el código predeterminado por el siguiente, que pertenece al


desencadenador Azure Functions Cosmos DB, para ver una lista de todos
los documentos actualizados. Este código permite imprimir la cantidad
de documentos que se actualizaron y la id del primer documento en la
consola Logs:
#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. De esta manera, finalizamos la integración de la colección de Cosmos DB y la


función de Azure. Ahora vamos a añadir un nuevo documento a la colección
y ver cómo actúa el desencadenador. Abra una nueva pestaña (sin cerrar
la pestaña cookbookdatacollectionTrigger en el explorador), navegue
hasta la colección y cree un nuevo documento haciendo clic en el botón
New Document, como se muestra en la siguiente captura de pantalla:

6. Después de reemplazar el JSON predeterminado (que solo tiene un atributo


id) por el JSON que posee los atributos necesarios, haga clic en el botón
Save para guardar los cambios y desplazarse rápidamente a la otra pestaña
del explorador, donde tiene abierta la función de Azure, para consultar
los registros y ver la salida de la función. A continuación, se muestra una
imagen de mis registros, ya que acabo de agregar un valor al atributo id del
documento. Es posible que sus registros luzcan diferente, dependiendo de su
estructura JSON:

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

Funcionamiento...
Para integrar Azure Functions con Cosmos DB, primero creamos una cuenta de
Cosmos DB y luego una base de datos y una nueva colección dentro de ella. Después
de crear la colección, la integramos desde el portal de Azure haciendo clic en el
botón Add Azure Function, disponible en la cuenta de Cosmos DB. Elegimos la
aplicación de función necesaria en la que queríamos crear un desencadenador de
Cosmos DB. Una vez completada la integración, creamos un documento de ejemplo
en la colección de Cosmos DB y luego comprobamos que la función se activara
automáticamente para todos los cambios (todas las lecturas y escrituras, pero no las
eliminaciones) que realizamos en la colección.

Aún hay más...


Al integrar Azure Functions para realizar un seguimiento de los cambios de Cosmos
DB, se creará automáticamente una nueva colección llamada leases, como se muestra
aquí. Recuerde que esto tiene un costo adicional, ya que el costo de Cosmos DB
depende de las unidades de solicitud (RU, request units) asignadas a cada colección:

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


desencadenará (en el momento de escribir) para las eliminaciones de la colección.
Solo se desencadena cuando se crean y actualizan documentos de una colección.
Si necesita hacer un seguimiento de las eliminaciones, debe realizar eliminaciones
temporales, lo cual significa configurar un atributo como isDeleted como
verdadero para los registros eliminados por la aplicación y, en base al valor del
atributo isDeleted, implementar su lógica personalizada en el desencadenador de
Cosmos DB.
La integración que realizamos entre Azure Functions y Cosmos DB contempla las
fuentes de cambio de Cosmos DB. Puede obtener más información sobre las fuentes
de cambios aquí: https://docs.microsoft.com/azure/cosmos-db/change-feed.
No olvide eliminar la cuenta de Cosmos DB y sus colecciones asociadas si cree que
ya no las utilizará, ya que las colecciones se cobran en función de las RU asignadas,
incluso si no las está utilizando de forma activa.
Si no puede ejecutar esta función de Azure o si aparece un error que dice que
las extensiones de Cosmos DB no están instaladas, intente crear un nuevo
desencadenador de Azure Cosmos DB, que luego solicitará la instalación.

[ 86 ]
Comprender la experiencia
integrada de desarrollador de
Visual Studio Tools
En este capítulo, trataremos los siguientes temas:
• Creación de una aplicación de función utilizando Visual Studio 2017.
• Depuración de funciones de Azure C# en un entorno local previamente
configurado utilizando Visual Studio 2017.
• Conexión con la nube de Azure Storage desde el entorno local de Visual
Studio.
• Implementación de la aplicación de función de Azure en la nube de Azure
utilizando Visual Studio.
• Depuración de la función de Azure C# activa, hospedada en el entorno de
nube de Microsoft Azure, con Visual Studio.
• Implementación de las funciones de Azure en un contenedor.

Introducción
En los capítulos anteriores, aprendimos cómo crear funciones de Azure directamente
desde el portal de administración de Azure. Estas son algunas de las características:

• Puede crear rápidamente una función seleccionando una de las plantillas


incorporadas proporcionadas por el tiempo de ejecución de la función de Azure.
• Los desarrolladores no necesitan preocuparse por escribir el código de
establecimiento y entender cómo funcionan los marcos.
• Los cambios de configuración se pueden realizar directamente dentro de
la interfaz de usuario utilizando el editor estándar.
[ 87 ]
Comprender la experiencia integrada de desarrollador de Visual Studio Tools

A pesar de todas las ventajas mencionadas, los desarrolladores podrían sentirse


incómodos si se acostumbraron a trabajar con sus entornos de desarrollo integrado
(IDE) favoritos hace mucho tiempo. Por lo tanto, el equipo de Microsoft creó algunas
herramientas que ayudan a que los desarrolladores las integren en Visual Studio
para que puedan aprovechar algunas de las características críticas del IDE que
aceleran sus esfuerzos de desarrollo. Estas son algunas de ellas:

• Los desarrolladores se benefician de la compatibilidad con IntelliSense.


• Es posible depurar el código línea por línea.
• Permite ver rápidamente los valores de las variables mientras se está
depurando la aplicación.
• Se integra con sistemas de control de versiones como Azure DevOps
(anteriormente, esto se llamaba Visual Studio Team Services [VSTS]).

Hoy en día, mientras escribo, las herramientas de Visual Studio para la función
admiten la depuración solo para C#. En el futuro, es probable que Microsoft ponga
a disposición todas estas características geniales en otros idiomas.

En este capítulo, aprenderá algunas de las características mencionadas y, en el


Capítulo 11, Implementar y facilitar la integración continua utilizando Azure DevOps, verá
cómo integrar el código con Azure DevOps.

Creación de una aplicación de función


utilizando Visual Studio 2017
En esta tarea, aprenderá a crear una función de Azure para su IDE favorito en Visual
Studio 2017.

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

1. Descargue la versión más reciente de Visual Studio 2017. Puede hacerlo


desde https://visualstudio.microsoft.com/downloads/.
2. Durante la instalación, elija la opción Azure development en la pestaña
Workloads, como se muestra en la siguiente captura de pantalla, y luego
haga clic en el botón Install :

[ 88 ]
Capítulo 4

3. Diríjase a Tools | Extensions and Updates y fíjese si hay alguna


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

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

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Abra Visual Studio, elija File y luego haga clic en New Project. En el cuadro
de diálogo New Project, en la plantilla Installed, dentro de Visual C#,
seleccione Cloud y luego la opción Azure Functions:

2. Proporcione el nombre de la aplicación de función. Haga clic en el botón OK


para avanzar al siguiente paso. Como se muestra en la siguiente captura de
pantalla, elija Azure Funtions v2 (.NET Core) en el menú desplegable. Luego
seleccione Http trigger y haga clic en el botón OK:

[ 90 ]
Capítulo 4

3. Hemos creado con éxito la aplicación de función de Azure, junto con un


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

Hemos creado correctamente una nueva aplicación de función desencadenada por


HTTP utilizando Visual Studio 2017.

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

Funcionamiento...
Las herramientas de Visual Studio para Azure Functions les permiten a los
desarrolladores utilizar su IDE favorito, el cual, posiblemente, hayan estado
utilizando por años. Con las herramientas de función de Azure, puede utilizar el
mismo conjunto de plantillas que proporciona el portal de administración de Azure
para crear e integrar rápidamente con los servicios en la nube sin escribir ningún
código de establecimiento (o escribiendo uno mínimo).
La otra ventaja de utilizar las herramientas de Visual Studio para las funciones es
que no es necesario tener una suscripción de Azure activa. Puede depurar y probar
las funciones de Azure directamente en el entorno de desarrollo local. La CLI de
Azure y las utilidades relacionadas nos proporcionan toda la asistencia necesaria
para ejecutar las funciones de Azure.

Aún hay más...


Uno de los problemas más comunes que enfrentan los desarrolladores al desarrollar
cualquier aplicación en su entorno local es que todo funciona bien en mi máquina local,
pero no en el entorno de producción. Los desarrolladores no tienen que preocuparse por
esto en el caso de las funciones de Azure. El tiempo de ejecución de las funciones
de Azure proporcionado por las herramientas de la CLI de Azure es exactamente el
mismo que el tiempo de ejecución disponible en la nube de Azure.

Tenga en cuenta que siempre puede utilizar y desencadenar un servicio


de Azure que se ejecuta en la nube, incluso cuando está desarrollando
funciones de Azure a nivel local.

Depuración de funciones de Azure C# en


un entorno local previamente configurado
utilizando Visual Studio 2017
Cuando completemos la configuración básica de la creación de nuestra función, el
siguiente paso es comenzar a trabajar en el desarrollo de la aplicación según sus
necesidades. El desarrollo de código a diario no es nada sencillo. Los desarrolladores
terminan enfrentando todo tipo de problemas técnicos. Necesitan herramientas
para ayudarles a identificar la causa del problema y a corregirlo para asegurarse de
brindar la solución. Entre ellas, se incluyen herramientas de depuración que ayudan
a los desarrolladores a entrar 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 tarea, aprenderá a configurar y depurar una función de Azure en un entorno
de desarrollo local dentro de Visual Studio.
[ 92 ]
Capítulo 4

Preparación
Descargue e instale la CLI de Azure (si no tiene instaladas estas herramientas, tenga
en cuenta que Visual Studio las descargará automáticamente cuando ejecute las
funciones desde Visual Studio).

Procedimiento...
Lleve a cabo los pasos siguientes:

1. En la tarea anterior, creamos la función HTTPTrigger utilizando Visual


Studio. Ahora crearemos la aplicación. Para ello, haga clic en Build y luego
en Build Solution.
2. Abra el archivo HTTPTriggerCSharpFromVS.cs y cree un punto de
interrupción presionando la tecla F9, como se muestra aquí:

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

3. Presione la tecla F5 para iniciar la depuración de la función. Al presionar F5


por primera vez, Visual Studio le pedirá que descargue las herramientas de
la CLI de Visual Studio si aún no están instaladas. Estas herramientas son
esenciales para ejecutar una función de Azure en Visual Studio:

Ahora se ha cambiado el nombre de la CLI de función de Azure


a Azure Function Core Tools. Puede obtener más información
al respecto en https://www.npmjs.com/package/azure-
functions-core-tools.

4. Al hacer clic en Yes en la captura de pantalla anterior, se comenzarán


a descargar las herramientas de la CLI. La descarga e instalación de las
herramientas de la CLI tardará unos minutos.
5. Después de instalar correctamente las herramientas de la CLI de función
de Azure, se creará e iniciará un host de trabajo. Comenzará a supervisar
las solicitudes en un puerto específico para todas las funciones de nuestra
aplicación de función. La siguiente captura de pantalla muestra que el host
de trabajo ha comenzado a supervisar las solicitudes a la aplicación de
función:

[ 94 ]
Capítulo 4

6. Intentaremos acceder a la aplicación de función enviando una solicitud


a http://localhost:7071 a través de su explorador de preferencia:

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

7. Escriba la dirección URL completa de nuestro desencadenador HTTP en el


explorador. Debe verse así: http://localhost:7071/api/HttpTriggerCsh
arpFromVS?name=Praveen Sreeram.
8. Después de escribir la URL correcta de la función de Azure, tan pronto
como presionamos la tecla Enter en la barra de direcciones del explorador,
el depurador de Visual Studio alcanza el punto de depuración (si tiene uno),
como vemos en esta captura de pantalla:

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


siguiente captura de pantalla:

10. Una vez completa la depuración, puede hacer clic en la tecla F5 para
completar el proceso de ejecución. Después de esto, verá 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 aparecerá en la consola del host del


trabajo, como se muestra en la siguiente captura de pantalla:

[ 96 ]
Capítulo 4

12. Puede agregar más funciones de Azure a la aplicación de función si es


necesario. En la siguiente tarea, veremos cómo conectarnos a la nube de
Azure Storage desde el entorno local.

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

La consola del host de trabajo le brinda los siguientes detalles:

• 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.

Aún hay más...


Con Visual Studio, puede crear funciones previamente compiladas, lo que significa
que, al compilar las funciones, Visual Studio crea un archivo .dll al que se puede
hacer referencia en otras aplicaciones, tal como lo hace para las clases normales.
A continuación se presentan dos de las ventajas de utilizar funciones previamente
compiladas:

• Las funciones previamente compiladas tienen un mejor rendimiento, ya que


no es necesario compilarlas sobre la marcha.
• Puede convertir sus clases tradicionales en funciones de Azure fácilmente
y hacer referencia a ellas en otras aplicaciones sin problemas.

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

Conexión con la nube de Azure Storage


desde el entorno local de Visual Studio
En las dos tareas anteriores, aprendió a crear y ejecutar funciones de Azure en un
entorno local. Desencadenamos la función desde un navegador local. Sin embargo,
en esta tarea aprenderá a desencadenar una función de Azure en su entorno local
cuando ocurre un evento en Azure. Por ejemplo, cuando se crea un nuevo blob en
una cuenta de Azure Storage, puede desencadenar la función en su equipo local. Esto
ayuda a que los desarrolladores prueben sus aplicaciones con antelación, antes de
implementarlas en el entorno de producción.

Preparación
Siga estos requisitos previos:

1. Cree una cuenta de almacenamiento y, luego, un contenedor de blobs


llamado cookbookfiles en Azure.
2. Instale el explorador de Microsoft Azure Storage desde
http://storageexplorer.com/.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Abra la aplicación de función de Azure FunctionAppInVisualStudio en


Visual Studio y, luego, agregue una nueva función haciendo clic derecho en
el proyecto FunctionAppInVisualStudio. Haga clic en Add | New Azure
Function, con lo cual se abrirá una ventana emergente. Aquí, para el campo
de nombre, escriba BlobTriggerCSharp y haga clic en el botón Add.
2. Con esto se abre otra ventana emergente, donde puede 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, ingrese


AzureWebJobsStorage como nombre de la cadena de conexión y también
especifique el nombre del contenedor de blobs (en mi caso, es cookbookfiles)
en el campo de entrada Path. Luego haga clic en el botón OK para crear una
nueva función de desencadenador de blobs. Así se crea una nueva función de
desencadenador de blobs, como se muestra en la siguiente captura de pantalla:

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

4. Si recuerda la tarea Compilación de una API web de back-end utilizando


desencadenadores HTTP en el Capítulo 1, Desarrollo de aplicaciones en la nube
utilizando desencadenadores de funciones y enlaces, el portal de administración
de Azure nos permitió elegir entre una cuenta de almacenamiento nueva
o actual. Sin embargo, el cuadro de diálogo anterior no está conectado
a su suscripción de Azure. Por lo tanto, debe desplazarse a la cuenta de
almacenamiento y copiar la cadena de conexión, que se encuentra en la hoja
Access Keys de la cuenta de almacenamiento en el portal de administración
de Azure, como se muestra en la siguiente captura de pantalla:

5. Pegue la cadena de conexión en el archivo local.settings.json, ubicado


en la carpeta root del proyecto. Este archivo se crea al crear la aplicación
de función. Después de agregar la cadena de conexión a la clave llamada
AzureWebJobsStorage, el archivo local.settings.json debe verse como
el que se muestra en la siguiente captura de pantalla:

6. Abra el archivo BlobTriggerCSharp.cs y cree un punto de interrupción,


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

7. Ahora presione la tecla F5 para iniciar el host de trabajo, como se ve


a continuación:

8. He agregado un nuevo archivo de blob utilizando el explorador de Azure


Storage, como se ve en la siguiente captura de pantalla:

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

9. Inmediatamente después de agregar el blob al contenedor específico (en este


caso, cookbookfiles), depositado en la nube en una ubicación remota, el
host de trabajo que se ejecuta en mi máquina local detecta que se ha añadido
un nuevo blob y el depurador inicia la función, como vemos en la siguiente
captura de pantalla:

Funcionamiento...
En esta clase BlobTriggerCSharp, el método Run posee atributos de WebJobs con una
cadena de conexión (en este caso, AzureWebJobsStorage). Esto le indica al tiempo
de ejecución que se remita a la cadena de conexión de Azure Storage en el archivo
de configuración local con la clave denominada al igual que la cadena de conexión
AzureWebJobsStorage. Cuando el host de trabajo comienza a ejecutarse, emplea la
cadena de conexión y supervisa los contenedores de cuentas de almacenamiento que
hemos especificado. Cada vez que se agrega o actualiza un blob nuevo, desencadena
automáticamente el desencadenador de blobs en el entorno actual.

Aún hay más...


Al crear funciones de Azure en el portal de administración de Azure, es necesario
crear desencadenadores y enlaces de salida en la pestaña Integrate de cada función
de Azure. Sin embargo, cuando se crea una función desde el IDE de Visual Studio
2017, basta configurar los atributos de WebJobs para lograrlo.

Puede 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

Implementación de la aplicación de
función de Azure en la nube de Azure
utilizando Visual Studio
Hasta ahora, nuestra aplicación de función solo es una aplicación normal dentro de
Visual Studio. Para implementar la aplicación de función junto con sus funciones,
necesitamos crear los siguientes recursos nuevos o seleccionar los existentes para
hospedar la nueva aplicación de función:
• El grupo de recursos.
• El plan de App Service.
• La aplicación de función de Azure.
Puede proporcionar todos estos detalles directamente desde Visual Studio sin abrir
el portal de administración de Azure. Aprenderá a hacerlo en esta tarea.

Procedimiento...
Lleve a cabo los pasos siguientes:
1. Haga clic derecho en el proyecto y luego haga clic en el botón Publish para
abrir la ventana de publicación.
2. En la ventana Publish, elija la opción Create New y haga clic en el botón
Publish, como se muestra en la siguiente captura de pantalla:

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

3. En la ventana Create App Service, puede elegir entre los recursos existentes
o hacer clic en el botón New para seleccionar el nuevo grupo de recursos en
Resource Group, el plan de App Service y la cuenta de almacenamiento en
Storage Account, como se ve a continuación:

4. En la mayoría de los casos, lo mejor es optar por el plan de consumo para


hospedar funciones de Azure, a menos que tenga un buen motivo para no
hacerlo y prefiera utilizar uno de sus App Services existentes. Para elegir
el plan de consumo, haga clic en el botón New que está disponible para el
plan de App Service, como se muestra en la captura de pantalla anterior.
Seleccione Consumption en el menú desplegable Size y haga clic en el botón
OK, como aparece a continuación:

[ 104 ]
Capítulo 4

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


la ventana Create App Service. Con esto se comienza a implementar los
servicios en Azure, como se muestra en la siguiente captura de pantalla:

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


de administración de Azure, como vemos aquí:

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

7. ¡Espere! Nuestro trabajo en Visual Studio aún no ha terminado. Solo


terminamos de crear los servicios necesarios en Azure directamente desde el
IDE de Visual Studio. Nuestro siguiente trabajo consiste en publicar el código
de la estación de trabajo local en la nube de Azure. Tan pronto como se
complete la implementación, el sistema lo dirigirá al paso de implementación
web, como se muestra en la captura de pantalla más abajo. Haga clic en el
botón Publish para iniciar el proceso de publicación del código:

8. Después de unos segundos, aparecerá algo similar a la siguiente captura de


pantalla en la ventana Output de la instancia de Visual Studio:

9. Eso es todo. Hemos terminado la implementación de la aplicación de


función y sus funciones en Azure directamente desde su IDE de desarrollo
favorito, Visual Studio. Puede revisar la implementación de la función en el
portal de administración de Azure. Ambas funciones de Azure se crearon
correctamente, como se muestra en la siguiente captura de pantalla:

[ 106 ]
Capítulo 4

Aún hay más...


Las funciones de Azure que se crean a partir de Visual Studio 2017 están
previamente compiladas, lo que significa que se implementan los archivos .dll de
Visual Studio 2017 en Azure. Por lo tanto, no puede editar el código de las funciones
en Azure después de implementarlas. Sin embargo, puede realizar cambios en las
configuraciones, tales como cambiar la cadena de conexión de Azure Storage, la
ruta de acceso del contenedor y así sucesivamente. Veremos cómo hacer esto en la
siguiente tarea.

Depuración de una función de Azure C#


activa hospedada en el entorno de nube
de Microsoft Azure con Visual Studio
En una de las tareas anteriores, Conectarse con la nube de Azure Storage desde el
entorno local de Visual Studio, aprendió a conectar la cuenta de almacenamiento
en la nube desde el código local. En esta tarea, aprenderá a depurar el código
activo que se ejecuta en el entorno de nube de Azure. Vamos a llevar a cabo los
pasos siguientes en la función BlobTriggerCSharp de la aplicación de función
FunctionAppinVisualStudio:

• Cambiar la ruta de acceso 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 Visual Studio 2017 a la función de Azure
correspondiente.
• Crear un blob en el nuevo contenedor de almacenamiento.
• Depurar la aplicación después de alcanzar los puntos de interrupción.

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

Preparación
Cree un contenedor llamado cookbookfiles-live en la cuenta de almacenamiento.
Subiremos un blob en este contenedor.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a la función BlobTriggerCSharp en el portal de administración de


Azure y cambie la ruta de acceso de la variable path para señalar el nuevo
contenedor cookbookfiles-live. A continuación, vuelva a publicarlo. Debe
verse como se muestra en la siguiente captura de pantalla:

2. Abra la aplicación de función en Visual Studio 2017. Luego abra el


explorador de servidores y diríjase a la función de Azure que, en este caso es
FunctionAppinVisualStudio2017, como se ve aquí:

[ 108 ]
Capítulo 4

3. Haga clic derecho en la función y luego haga clic en Attach Debugger, como
se ve en la siguiente captura de pantalla:

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

4. Visual Studio tardará cierto tiempo en habilitar la depuración remota, como


se muestra en la siguiente captura de pantalla:

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


en la captura de pantalla más abajo, lo cual indica que nuestra aplicación de
función se está ejecutando:

6. Diríjase a Storage Explorer y cargue un nuevo archivo (en este caso, cargué
EmployeeInfo.json) en el contenedor cookbookfiles-live, como se
muestra aquí:

[ 110 ]
Capítulo 4

7. Después de unos instantes, se alcanzará el punto de interrupción de depuración,


como se ve más abajo, donde puede ver el nombre de archivo cargado:

Implementación de las funciones de


Azure en un contenedor
A esta altura, ya debe haber comprendido el caso de uso principal de por qué
preferimos utilizar las funciones de Azure. Sí, al desarrollar un fragmento de código
e implementarlo en un entorno sin servidor, donde un desarrollador o administrador
no tiene que preocuparse por el aprovisionamiento y el escalado de las instancias
para hospedar las aplicaciones del lado del servidor.

Solo se pueden realizar todas las características del entorno sin


servidor al crear la aplicación de función, es decir, eligiendo el
plan de consumo en el menú desplegable Hosting Plan.

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

Al ver el título de esta tarea, quizá se haya preguntado por qué y cómo podría
ayudar la implementación de una función de Azure en un contenedor de Docker.
Efectivamente, es posible que la combinación de las funciones de Azure y el
contenedor de Docker no tenga sentido, ya que perdería todas las ventajas del
servicio sin servidor de Azure Functions al implementarlas en Docker. Sin embargo,
puede haber algunos clientes cuyas cargas de trabajo actuales se encuentren en algún
tipo de nube (ya sea pública o privada) y que ahora quieran aprovechar algunos de
los desencadenadores de funciones de Azure y los servicios de Azure relacionados,
por lo que desean implementar las funciones de Azure como una imagen de Docker.
En esta tarea se explica cómo implementar este procedimiento.

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

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


install-azure-cli?view=azure-cli-latest.
• Puede descargar Docker desde https://store.docker.com/editions/
community/docker-ce-desktop-windows. Asegúrese de instalar la versión
de Docker que sea compatible con el sistema operativo del entorno de
desarrollo.
• También es necesario tener conocimientos básicos sobre Docker y sus
comandos para compilar y ejecutar imágenes de Docker. Si lo desconoce,
puede consultar la documentación oficial de Docker para obtener
información al respecto.
• Siga los pasos a continuación para crear el registro Azure Container Registry
(ACR). Puede utilizarlo como repositorio para todas las imágenes de Docker.

[ 112 ]
Capítulo 4

Crear un ACR
Lleve a cabo los pasos siguientes:

1. Brinde los siguientes detalles para crear un nuevo ACR, como se muestra en
esta captura de pantalla:

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

2. Después de crear correctamente el ACR, desplácese hasta la hoja Access


Keys y tome nota de los campos Login server, Username y password, que se
resaltan a continuación. Los utilizaremos más adelante en esta tarea:

Procedimiento...
En los tres primeros capítulos, creamos tanto la aplicación de función como las
funciones directamente en el portal. Hasta ahora, en este capítulo, hemos creado la
aplicación de función y las funciones en Visual Studio.

Antes de empezar, hagamos un pequeño cambio en httptrigger para comprobar


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

[ 114 ]
Capítulo 4

Crear una imagen de Docker para la


aplicación de función
Lleve a cabo los pasos siguientes:

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


Dockerfile en nuestro proyecto de Visual Studio. Cree un archivo
.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, crearemos una imagen de Docker. Para ello, diríjase al


símbolo del sistema y ejecute el comando de Docker, docker build -t
functionsindocker, con cuidado de no omitir el espacio al final del
comando. Después de ejecutar el comando docker build, debe aparecer
algo similar a esta captura de pantalla:

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


ejecutar la imagen de Docker en un puerto específico. Para ello, ejecute el
comando. Debe ver algo como lo siguiente:

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

4. Para comprobar que todo funciona bien en el entorno local, diríjase al host
local con el puerto correcto, como se muestra en la siguiente captura de
pantalla.

Insertar la imagen de Docker en el ACR


Lleve a cabo los pasos siguientes:
1. El primer paso es asegurarse de brindar una etiqueta válida para la
imagen utilizando el comando docker tag functionsindocker
cookbookregistry.azurecr.io/functionsindocker:v1. La ejecución de
este comando no proporcionará ninguna salida. Sin embargo, para ver los
cambios que hicimos, vamos a ejecutar el comando docker images, como se
muestra aquí:

2. Para insertar la imagen en el ACR, debe autenticarse en Azure. Puede utilizar


los comandos de la CLI de Azure para realizarlo. Iniciaremos sesión en
Azure empleando el comando az login. Al ejecutar este comando, se abrirá
un explorador y se autenticarán sus credenciales, como se muestra en la
siguiente captura de pantalla:

[ 116 ]
Capítulo 4

3. El próximo paso es autenticarse en el ACR utilizando el comando az acr


login --name cookbookregistry. Reemplace el nombre del ACR (en este
caso, es cookbookregistry) por el que ha creado:

4. Una vez que se haya autenticado, inserte la imagen en el ACR


ejecutando el comando docker push cookbookregistry.azurecr.io/
functionsindocker:v1, como vemos aquí:

5. Vayamos al ACR en el portal de Azure y verifiquemos si nuestra imagen


se insertó correctamente en la hoja Repositories, como se muestra en esta
captura de pantalla:

Acabamos de crear correctamente una imagen e insertarla en el ACR. Ahora es el


momento de crear la función de Azure y hacer referencia a la imagen de Docker que
insertamos en el ACR.

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

Crear una nueva aplicación de función con


Docker
Lleve a cabo los pasos siguientes:
1. Diríjase a la hoja New | Function App y especifique la siguiente información:

2. Ahora elija Linux (Preview) en el campo OS y luego Docker Image en el


campo Publish. Haga clic en App Service Plan/Location, como se detalla en
la captura de pantalla anterior. Aquí elija crear un nuevo plan básico de App
Service en el campo Basic.

[ 118 ]
Capítulo 4

3. El paso siguiente, y el más importante, es referir la imagen que enviamos al


ACR. Para ello, haga clic en el botón Configure container y elija Azure
Container Registry. A continuación, seleccione la imagen correcta, como
se muestra aquí:

4. Después de repasar todos los detalles, haga clic en el botón Create 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 vinculándola a la imagen hospedada
en Azure Container Registry. Probemos rápidamente el desencadenador
HttpTrigger navegando al punto de conexión HTTP en el explorador.
A continuación, se muestra la salida de la función de Azure.

Funcionamiento...
En los tres primeros capítulos, creamos tanto la aplicación de función como las
funciones directamente en el portal. Por el contrario, hasta ahora en este capítulo
hemos creado la aplicación de función y las funciones en Visual Studio.

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

En esta tarea, hicimos lo siguiente:

Los números en este diagrama hacen referencia a estos pasos:

1. Cree una imagen de Docker de la aplicación de función que creamos en este


capítulo con Visual Studio.
2. Inserte la imagen de Docker en el ACR.
3. Desde el portal, cree una nueva aplicación de función y elija publicar el
paquete ejecutable como una imagen de Docker.
4. Adjunte la imagen de Docker del ACR (según el paso 2 de la guía anterior)
a la función de Azure (según el paso 3 de la guía anterior).

[ 120 ]
Explorar las herramientas
de prueba para validar las
funciones de Azure
En este capítulo, vamos a explorar diferentes maneras de probar las funciones
de Azure de forma más detallada con las siguientes tareas:
• Prueba de las funciones de Azure:
°° Prueba de los desencadenadores HTTP utilizando Postman.
°° Prueba del desencadenador de blobs utilizando el explorador
de almacenamiento de Microsoft.
°° Prueba del desencadenador de cola utilizando el portal
de administración de Azure.
• Prueba de una función de Azure en un entorno previamente configurado
utilizando ranuras de implementación.
• Prueba de carga de las funciones de Azure mediante Azure DevOps.
• Creación y prueba de una función de Azure de manera local con
herramientas de la CLI de Azure.
• Prueba y validación de la capacidad de respuesta de una función de Azure
utilizando Application Insights.
• Desarrollo de pruebas unitarias para las funciones de Azure con
desencadenadores HTTP.

Introducción
En los capítulos anteriores, aprendió a desarrollar funciones de Azure y a reconocer
dónde son útiles, además de analizar la validación de su funcionalidad.

[ 121 ]
Explorar las herramientas de prueba para validar las funciones de Azure

En este capítulo, comenzaremos analizando varias formas de probar diferentes


funciones de Azure. Esto incluye, por ejemplo, ejecutar pruebas de funciones
de desencadenador HTTP utilizando Postman y utilizar el explorador
de almacenamiento de Microsoft para probar desencadenadores de blobs de Azure,
desencadenadores de cola y demás desencadenadores relacionados con el servicio
de almacenamiento. También aprenderá a realizar una prueba de carga sencilla
en un desencadenador HTTP para comprender cómo funciona la arquitectura sin
servidor aprovisionando las instancias en el back-end, sin que los desarrolladores
tengan que preocuparse por la configuración de escalado en diferentes factores. El
tiempo de ejecución de la función de Azure se encargará automáticamente de escalar
las instancias.

También aprenderá a configurar una prueba para comprobar la disponibilidad


de nuestras funciones haciendo ping una y otra vez en los puntos de conexión
de la aplicación a una frecuencia previamente definida desde varias ubicaciones.

Prueba de las funciones de Azure


El tiempo de ejecución de las funciones de Azure nos permite crear e integrar
muchos servicios de Azure. En el momento de elaboración de este libro, se pueden
crear más de 20 tipos de funciones de Azure. En esta tarea, aprenderá a probar las
funciones de Azure más comunes, que se enumeran a continuación:

• Prueba de los desencadenadores HTTP utilizando Postman.


• Prueba del desencadenador de blobs utilizando el explorador
de almacenamiento de Microsoft.
• Prueba del desencadenador de cola utilizando el portal de administración
de Azure.

Preparación
Instale las siguientes herramientas, si aún no las tiene:

• Postman: puede descargarla desde https://www.getpostman.com/.


• Explorador de Microsoft Azure Storage: puede descargarla desde
http://storageexplorer.com/.

Puede utilizar el explorador de Storage para conectarse a las cuentas de


almacenamiento y ver todos los datos disponibles de diferentes servicios de
almacenamiento, como blobs, colas, tablas y archivos. También puede crearlos,
actualizarlos y eliminarlos directamente desde el explorador de almacenamiento.

[ 122 ]
Capítulo 5

Procedimiento...
En esta sección, crearemos tres funciones de Azure 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 HTTP utilizando


Postman
Lleve a cabo los pasos siguientes:

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


Firstname y Lastname, y los envíe en la respuesta. Una vez creada,
compruebe que Authorization Level esté configurado como Anonymous.
2. Reemplace el código predeterminado por el siguiente. Tenga en cuenta que
quité las validaciones para simplificar la tarea. En las aplicaciones en tiempo
real, tiene que validar cada uno de 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 prueba para validar las funciones de Azure

3. Abra la herramienta Postman y complete lo siguiente:


1. E
 l primer paso es elegir el tipo de método HTTP con el que desea
realizar la solicitud de HTTP. Debido a que esta función acepta la
mayoría de los métodos de forma predeterminada, elija el método
GET, como se muestra aquí:

2. El siguiente paso es proporcionar la URL del desencadenador HTTP.


Recuerde reemplazar <HttpTriggerTestUsingPostman> por el
nombre real de su función HttpTrigger, de esta manera:

4. Haga clic en el botón Send para hacer la solicitud. Si especificó todos los
detalles necesarios para la API, verá Status: 200 OK, junto con la respuesta,
como figura aquí:

5.

[ 124 ]
Capítulo 5

Probar un desencadenador de blobs utilizando el


explorador de almacenamiento de Microsoft
Lleve a cabo los pasos siguientes:

1. Para crear un nuevo desencadenador de blobs, elija la plantilla Azure Blob


Storage trigger, como se detalla aquí:

2. Una vez que haga clic en la plantilla que se observa en la captura de pantalla
anterior, el sistema le pedirá que proporcione la cuenta de almacenamiento
y el contenedor donde almacenará el blob, como se muestra aquí:

[ 125 ]
Explorar las herramientas de prueba para validar las funciones de Azure

3. Vamos a conectarnos con la cuenta de almacenamiento que utilizaremos en


esta tarea. Abra Microsoft Azure Storage Explorer y haga clic en el botón
resaltado en la siguiente captura de pantalla para conectarse con Azure
Storage:

4. El sistema le pedirá que especifique algunos detalles, incluida la cadena


de conexión de almacenamiento, la firma de acceso compartido (SAS) y la
clave de su cuenta. Para esta tarea, vamos a utilizar la cadena de conexión
de almacenamiento. Diríjase a la cuenta de almacenamiento, copie la cadena
de conexión en la hoja Access Keys y péguela en la ventana emergente
Microsoft Azure Storage Explorer - Connect, de este modo:

[ 126 ]
Capítulo 5

5. Después de hacer clic en el botón Next en la captura de pantalla anterior,


aparecerá la ventana Connection Summary con el nombre de la cuenta
y demás detalles relacionados para confirmar. Haga clic en el botón Connect
para conectarse a la cuenta de Azure Storage elegida.
6. Como se muestra en la captura de pantalla más abajo, ahora está conectado
a la cuenta de Azure Storage, donde puede administrar todos los servicios
de Azure Storage:

7. Ahora vamos a crear un contenedor de almacenamiento llamado samples-


workitems. Haga clic derecho en la carpeta Blob Containers y luego haga
clic en Create Blob Container para crear un nuevo contenedor de blobs
denominado samples-workitems. A continuación, haga clic en el botón
Upload files, como se muestra en esta captura de pantalla:

8. En la ventana Upload Files, elija el archivo que desea cargar y haga clic en el
botón Upload.

[ 127 ]
Explorar las herramientas de prueba para validar las funciones de Azure

9. Diríjase de inmediato al editor de código de la función de Azure y observe


la ventana Logs, como se ilustra aquí: En el registro se muestra la función
de Azure desencadenada correctamente:

Probar el desencadenador de cola utilizando


el portal de administración de Azure
Lleve a cabo los pasos siguientes:

1. Cree un nuevo desencadenador de cola de Azure Storage llamado


QueueTriggerTestusingPortal, como se muestra más abajo. Anote
el nombre de la cola, myqueue-items, ya que vamos a crear un servicio
de cola con el mismo nombre más adelante utilizando el portal de
administración de Azure:

[ 128 ]
Capítulo 5

2. Diríjase a la hoja Overview de la cuenta de almacenamiento y haga clic en


Queues, como se muestra en esta captura de pantalla:

3. En la hoja Queue service, haga clic en Queue para agregar una nueva cola:

4. Ingrese myqueue-items en Queue name en la ventana emergente


Add queue, como se muestra en esta captura de pantalla. Este es el mismo
nombre que utilizamos al crear el desencadenador de cola. Haga clic en
OK para crear el servicio Queue service:

[ 129 ]
Explorar las herramientas de prueba para validar las funciones de Azure

5. Ahora tenemos que crear un mensaje de cola. En el portal de administración


de Azure, haga clic en el servicio de cola myqueue-items para desplazarse
a la hoja Messages. Haga clic en el botón Add message, como se muestra
más abajo, e ingrese el texto del mensaje de cola. Por último, haga clic en OK
para crear el mensaje de cola:

6. A continuación, diríjase al desencadenador de cola


QueueTriggerTestusingPortal y observe la hoja Logs. Aquí puede ver
cómo se desencadenó la función de cola, como se muestra en la siguiente
captura de pantalla:

[ 130 ]
Capítulo 5

Aún hay más...


Para todos los desencadenadores HTTP, si desea que los consumidores de su API
utilicen solamente el método POST, puede configurar esta restricción eligiendo
Selected methods y marcando solo la casilla POST en Selected HTTP methods,
como se detalla aquí:

Prueba de una función de Azure en


un entorno previamente configurado
utilizando ranuras de implementación
En general, cada aplicación necesita entornos de preproducción, como
almacenamiento provisional, beta, etcétera, para revisar las funcionalidades antes de
publicarlas para los usuarios finales.

Aunque los entornos de preproducción son excelentes y ayudan a varias partes


interesadas a validar la funcionalidad de la aplicación con respecto a los requisitos
empresariales, existen ciertas dificultades al administrarlos y mantenerlos. Estos son
algunos de ellos:

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


de preproducción.
• Una vez que se revisó todo en la etapa de preproducción y el equipo de
operaciones de TI obtuvo la autorización para avanzar, habría un poco de
tiempo de inactividad en el entorno de producción al implementar el código
base de nuevas funcionalidades.

[ 131 ]
Explorar las herramientas de prueba para validar las funciones de Azure

Todas estas limitaciones están cubiertas en Azure Functions, ya que se emplea una
característica denominada slots, ranuras en español, (también se llaman deployment
slots o ranuras de implementación en los entornos de App Service). El uso de
ranuras permite configurar un entorno de preproducción donde se pueden revisar
todas las funcionalidades nuevas y promoverlas (mediante el intercambio que
abordaremos en un momento) al entorno de producción sin problemas y siempre
que lo necesite.

Procedimiento
Lleve a cabo los pasos siguientes:

1. Cree una nueva aplicación de función llamada MyProductionApp.


2. Cree un nuevo desencadenador HTTP y asígnele el nombre MyProd-
HttpTrigger1. Reemplace la última línea por:
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. Cree otro desencadenador HTTP con el nombre MyProd-HttpTrigger2.


Utilice el mismo código que usó para MyProd-HttpTrigger1 y solo
reemplace 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 las dos funciones de la aplicación de función están activas


en su entorno de producción con la URL https://<<functionappname.
azurewebsites.net>>.
5. Ahora el cliente nos pidió hacer algunos cambios en ambas funciones. En
lugar de hacer los cambios directamente en las funciones de la aplicación de
función de producción, cree una ranura.
6. ¡Espere! Antes de crear la ranura, primero tiene que habilitar la característica.
Para ello, diríjase a Function app settings debajo de General Settings en la
pestaña Platform features de la aplicación de función. Cuando haga clic en
Function app settings, se abrirá una nueva pestaña donde puede habilitar el
parámetro Slots (preview), como se muestra en esta captura de pantalla:

[ 132 ]
Capítulo 5

Actualmente, la función de ranuras está en versión preliminar.


Cuando lea esto, es posible que ya esté consignada como Generally
Available (GA). No se recomienda utilizar esta característica en
cargas de trabajo de producción hasta que pase a GA

7. Haga clic en el botón On en la sección Slots (preview) resaltada en la captura


de pantalla anterior. Tan pronto como la habilite, la sección de ranuras se
ocultará, ya que es un ajuste de una sola vez. Una vez que esté habilitada, no
podrá deshabilitarla.
8. Ahora vamos a crear una nueva ranura con todas las funciones que tenemos
en nuestra aplicación de función denominada MyProductionApp.
9. Haga clic en el icono +, ubicado cerca de la sección Slots (preview), como se
muestra en la siguiente captura de pantalla:

10. Se le pedirá que introduzca un nombre para la nueva ranura. Proporcione un


nombre significativo, como por ejemplo Staging, como se muestra aquí:

[ 133 ]
Explorar las herramientas de prueba para validar las funciones de Azure

11. Después de hacer clic en Create, se creará una nueva ranura, como podemos
ver en la siguiente captura de pantalla. Si ve las funciones como de solo
lectura, puede hacerlas de lectura y escritura en Function App Settings.

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


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

12. Para que el entorno preconfigurado esté completo, copie todas las
funciones de Azure del entorno de producción (en este caso, la aplicación
MyProductionApp) en la nueva ranura preconfigurada llamada Staging.
Cree dos desencadenadores HTTP y copie los dos códigos de función
(MyProd-HttpTrigger1 y MyProd-HttpTrigger2) de MyProductionApp en
la nueva ranura Staging. Básicamente, tiene que copiar todas las funciones
en la nueva ranura de forma manual.
13. Cambie la cadena production por staging en la última línea de las dos
funciones en la ranura Staging. Esto sirve para probar la salida de la
operación de intercambio:

[ 134 ]
Capítulo 5

Tenga en cuenta que, en todas las ranuras que cree como una aplicación
de preproducción, debe utilizar los mismos nombres de función que tiene
en su entorno de producción.

14. Haga clic en el botón Swap, ubicado en la hoja Deployment slots, como se
muestra en la siguiente captura de pantalla:

15. En la hoja Swap, elija:


°° Swap Type: elija la opción Swap.
°° Source: elija la ranura que desea mover a producción. En este caso,
estamos intercambiando Staging en general pero, si lo desea, puede
hacer intercambios entre ranuras de no producción.

[ 135 ]
Explorar las herramientas de prueba para validar las funciones de Azure

°° Destination: elija la opción production que se muestra en esta


captura de pantalla:

16. Después de repasar la configuración, haga clic en el botón OK en el paso


anterior. El sistema tardará un momento para intercambiar las funciones.
Aparecerá una barra de progreso, como se muestra aquí:

[ 136 ]
Capítulo 5

17. Al cabo de un minuto o dos, se completará el intercambio de las ranuras


Staging y Production. Veamos los archivos de script run.csx de la
producción:

18. Si no observa ningún cambio, haga clic en el botón de actualización de la


aplicación de función, como se muestra aquí:

[ 137 ]
Explorar las herramientas de prueba para validar las funciones de Azure

19. Compruebe que los campos Application settings y Database Connection


Strings estén marcados como Slot Setting (específico de la ranura). De
lo contrario, los campos Application settings y Database Connection
Strings también se intercambiarán, lo cual ocasionaría un comportamiento
imprevisto. Puede marcar cualquiera de estas configuraciones como
corresponde desde Platform features, como se detalla aquí:

20. Al hacer clic en Application settings, el sistema lo dirigirá a la siguiente hoja,


donde podrá marcar la configuración que desee como SLOT SETTING:

Todas las funciones abordadas en la tarea son desencadenadores HTTP.


Recuerde que puede tener cualquier tipo de desencadenadores en la
aplicación de función. Las ranuras de implementación no se limitan a
desencadenadores HTTP.
Puede tener múltiples ranuras para cada una de sus aplicaciones de
función. Estos son algunos ejemplos:
Alpha
Beta
Staging
[ 138 ]
Capítulo 5

Aún hay más...


Si intenta crear una ranura sin habilitar la característica de Deployment Slots,
aparecerá una pantalla similar a la que vemos aquí:

Debe tener todas las funciones de Azure en cada una de las ranuras que pretende
intercambiar con su 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.
• Una vez que habilita las características de las ranuras, se regeneran todas
las claves, incluso la clave maestra. Tenga cuidado si ya ha compartido las
claves de las funciones con terceros. Si ya las compartió y habilitó las ranuras,
ninguna de las integraciones existentes con las claves antiguas funcionará.

En general, si está utilizando App Services y quiere crear ranuras de implementación,


debe tener su plan de App Service en alguno de los niveles Estándar o Premium. No
obstante, puede crear ranuras para la aplicación de función incluso si se encuentran
en planes de consumo (o dinámicos).

Prueba de carga de las funciones de


Azure mediante Azure DevOps
Es necesario que cada aplicación funcione bien en términos del rendimiento. Todos
los miembros del equipo tienen la responsabilidad de hacer que la aplicación
funcione correctamente. En esta tarea, aprenderá a crear una carga en Azure
Functions empleando la herramienta Load Test proporcionada por Azure DevOps
(anteriormente conocida como VSTS). Esta tarea también le ayudará a comprender
cómo funciona el escalado automático de instancias en el entorno sin servidor, sin
que los desarrolladores o arquitectos tengan que preocuparse por las instancias
responsables de atender las solicitudes.

[ 139 ]
Explorar las herramientas de prueba para validar las funciones de Azure

Preparación
Cree una cuenta de Azure DevOps en https://visualstudio.microsoft.com/.
Utilizaremos la herramienta Load Test de Azure DevOps para crear pruebas de
carga basadas en URL.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree un nuevo desencadenador HTTP, llamado LoadTestHttpTrigger, con


el parámetro Authorization Level configurado en Anonymous.
2. Reemplace 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 se explica por sí mismo. Para que la prueba de carga


sea interesante, vamos a simular una carga de procesamiento agregando
un tiempo de espera de dos segundos. Para ello, utilizaremos System.
Threading. Thread. Sleep (2000);.
4. Copie la URL de la función haciendo clic en el enlace </> Get function URL
en el extremo derecho del editor de código run.csx.
5. Diríjase a la pestaña Load test en la cuenta de Azure DevOps. Puede
encontrarla en el menú Test, luego de iniciar sesión en Azure DevOps:

[ 140 ]
Capítulo 5

6. Haga clic en el enlace New y seleccione URL based test, como se muestra en
la siguiente captura de pantalla:

7. En la pestaña Web Scenarios, especifique un nombre significativo para la


prueba de carga, como figura aquí:

8. Pegue la URL del desencadenador HTTP que copió en el Paso 4 en el campo


de salida URL, como se detalla a continuación:

[ 141 ]
Explorar las herramientas de prueba para validar las funciones de Azure

9. Ahora haga clic en el botón Save para guardar la prueba de carga:

10. En el siguiente paso debe proporcionar detalles sobre la carga que queremos
crear en la función de Azure. Como se muestra en la captura de pantalla más
abajo, haga clic en Settings e indique los detalles de la prueba de carga que
desea, según sus requisitos:

[ 142 ]
Capítulo 5

11. Después de brindar todos los detalles de la prueba de carga, haga clic en
Save. Una vez que guarde la prueba, el botón Run test quedará habilitado,
como vemos en esta captura de pantalla:

12. Haga clic en Run test para iniciar la prueba de carga. Como la duración de la
ejecución de nuestra prueba de carga es de 20 minutos, tardará 20 minutos
en completar la prueba de carga. Una vez completada la carga, Azure
DevOps nos proporciona los informes de rendimiento, que se muestran a
continuación:
°° Informe de rendimiento: nos brinda el tiempo de respuesta
promedio del desencadenador HTTP para cargar 1000 usuarios.

Aún hay más...


También podemos consultar cómo Azure escala las instancias automáticamente
en segundo plano en la pestaña Live Metrics Stream de Application Insights.
La siguiente captura de pantalla muestra los ID de instancia y el estado de las
máquinas virtuales que se asignan de forma automática en función de la carga en la
arquitectura sin servidor de Azure. Aprenderá a integrar Application Insights con
Azure Functions en el Capítulo 6, Supervisar y solucionar problemas en los servicios sin
servidor de Azure.

[ 143 ]
Explorar las herramientas de prueba para validar las funciones de Azure

Consulte también
Puede encontrar más información sobre este tema en la tarea Supervisar las
funciones de Azure utilizando Application Insights en el Capítulo 6, Supervisar
y solucionar problemas en los servicios sin servidor de Azure.

Creación y prueba de las funciones de


Azure de manera local con herramientas
de la CLI de Azure
La mayoría de las tareas que aprendió hasta ahora se crearon a través del explorador
o del entorno de desarrollo integrado (IDE) de Visual Studio.

Azure también proporciona herramientas para los desarrolladores que aman trabajar
con la línea de comandos. Estas herramientas nos permiten crear recursos de Azure
con comandos simples directamente desde la línea de comandos. En esta tarea,
aprenderá a crear una nueva aplicación de función, además de crear una función
e implementarla en la nube de Azure directamente desde la línea de comandos.

[ 144 ]
Capítulo 5

Preparación
Lleve a cabo los pasos siguientes:

• Descargue e instale Node.js desde https://nodejs.org/en/download/.


• Descargue e instale las herramientas de la CLI de Azure desde
https://docs.microsoft.com/cli/azure/install-azure-
cli?view=azure-cli-latest.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Una vez que Azure Functions Core Tools esté listo, ejecute el siguiente
comando para crear una nueva aplicación de función:
func init

Obtendrá el siguiente resultado después de ejecutar el comando anterior:

[ 145 ]
Explorar las herramientas de prueba para validar las funciones de Azure

En la captura de pantalla que se muestra más arriba, dotnet aparece


seleccionado de forma predeterminada. Al presionar Enter, se crearán los
archivos requeridos, como se muestra en la siguiente captura de pantalla:

2. Ejecute el siguiente comando para crear una nueva función de


desencadenador HTTP dentro de la nueva aplicación de función que hemos
creado:
func new

Obtendrá el siguiente resultado después de ejecutar el comando anterior:

3. Como se muestra en la captura de pantalla anterior, el sistema le pedirá


que elija la plantilla de función. Para esta tarea, elegí HttpTrigger. Elija
HttpTrigger con la flecha abajo. Seleccione el tipo de función de Azure
según sus requisitos. Puede navegar entre las opciones utilizando las flechas
arriba/abajo del teclado.

[ 146 ]
Capítulo 5

4. El siguiente paso es proporcionar un nombre para la función de Azure que


está creando. Especifique un nombre significativo y presione Enter, como se
muestra aquí:

5. Puede utilizar su IDE favorito para editar el código de la función de Azure.


En esta tarea, usé Visual Studio Code para abrir la función HttpTrigger,
como vemos a continuación:

6. Vamos a probar la función de Azure directamente desde el equipo local.


Para ello, tenemos que iniciar el host de la función de Azure ejecutando el
siguiente comando:
func host start --build

[ 147 ]
Explorar las herramientas de prueba para validar las funciones de Azure

7. Una vez que se haya iniciado el host, copie la dirección URL y pruébelo en el
explorador, junto con un nombre de parámetro de cadena de consulta, como
se muestra en la siguiente captura de pantalla:

Prueba y validación de la capacidad


de respuesta de una función de Azure
utilizando Application Insights
Todas las aplicaciones son útiles para cualquier negocio siempre y cuando estén
en funcionamiento. Las aplicaciones pueden fallar por múltiples razones. Aquí
enumeramos algunas de ellas:

• Un error de hardware, como un bloqueo del servidor, un disco duro erróneo


o cualquier otro problema de hardware. Incluso un centro de datos completo
podría dejar de funcionar, aunque esto es poco frecuente.
• Puede haber errores de software debido a un código incorrecto o a un error
de implementación.
• El sitio puede recibir una cantidad de tráfico inesperada que los servidores
no pueden manejar.
• En algunos casos, se puede acceder a su aplicación desde un determinado
país, pero no desde otros.

Sería realmente útil recibir una notificación cuando nuestro sitio no está disponible
o no responde a las solicitudes de los usuarios. Azure proporciona algunas
herramientas que nos alertan si el sitio web no responde o no funciona. Una de ellas
es Application Insights. Aprenderá a configurar Application Insights para hacer ping
en nuestra aplicación de función de Azure cada minuto y a configurarla para que nos
avise si la función no responde.

[ 148 ]
Capítulo 5

Preparación
Lleve a cabo los pasos siguientes:

1. Diríjase al portal de administración de Azure, busque Application Insights,


haga clic en el botón Create y proporcione todos los detalles necesarios, como
se muestra aquí:

[ 149 ]
Explorar las herramientas de prueba para validar las funciones de Azure

2. Navegue hasta la hoja Overview de su aplicación de función y capte su URL,


como vemos en esta captura de pantalla:

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Desplácese hasta la hoja Availability y haga clic en el botón de prueba Add,


como se detalla aquí:

[ 150 ]
Capítulo 5

2. En la hoja Create test, ingrese un nombre significativo para su requisito y


pegue la URL de la aplicación de función, que captó en el Paso 2 de la sección
anterior llamada Preparación, en el campo URL de la hoja Create test. En la
hoja Alerts, ingrese una dirección de correo electrónico válida en el campo
Send alert emails to these email addresses:, donde se enviará una alerta si la
función no está disponible o no responde:

[ 151 ]
Explorar las herramientas de prueba para validar las funciones de Azure

3. Haga clic en OK en la hoja Alerts y luego haga clic en el botón Create de


la hoja Create test para crear la prueba, como se muestra más abajo, en la
sección All availability tests:

4. Para probar la funcionalidad de esta alerta, vamos a detener la aplicación de


función haciendo clic en el botón Stop ubicado en la pestaña Overview de la
aplicación de función.

[ 152 ]
Capítulo 5

5. Cuando se detiene la aplicación de función, Application Insights intenta


acceder a la dirección URL de la función utilizando la prueba de ping. El
código de respuesta ya no será 200, ya que la aplicación se detuvo, lo que
significa que la prueba falló y se debería haber enviado una notificación al
correo electrónico configurado, como se observa en esta captura de pantalla:

Funcionamiento...
Creamos la prueba Availability, donde se hará ping en nuestra aplicación de
función cada cinco minutos desde cinco ubicaciones diferentes del mundo, como
máximo. Puede configurarlas en la pestaña Test Location de la hoja Create test
mientras crea 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, entonces
la prueba ha fallado y se envía una alerta a la dirección de correo electrónico
configurable.

Aún hay más...


Puede emplear una prueba web de varios pasos (utilizando la opción Test Type en
la hoja Create test) si desea probar una página o funcionalidad que requiera navegar
a muchas páginas.

Desarrollo de pruebas unitarias


para las funciones de Azure con
desencadenadores HTTP
Hasta ahora, hemos creado varias funciones de Azure y validado su funcionalidad
utilizando diferentes herramientas. Las características de las funciones que
desarrollamos hasta el momento son bastante simples y directas. Sin embargo, en
las aplicaciones reales, no será tan simple. Probablemente haya muchos cambios

[ 153 ]
Explorar las herramientas de prueba para validar las funciones de Azure

en el código que creamos al inicio. Una buena práctica es escribir pruebas unitarias
automatizadas que nos ayuden a probar la funcionalidad de nuestras funciones de
Azure. Cada vez que ejecutamos estas pruebas unitarias automatizadas, podemos
probar las diversas rutas de acceso dentro del código.

En esta tarea, aprenderemos a utilizar el desencadenador HTTP básico y veremos


lo fácil que es escribir casos de pruebas unitarias automatizadas para este fin
empleando el explorador de pruebas de Visual Studio y Moq (un marco de open
source disponible como un paquete de NuGet).

Preparación
Vamos a utilizar el marco de simulación de Moq para realizar una prueba unitaria
en nuestra función de Azure. Para esta tarea, se requieren conocimientos prácticos
básicos de Moq. Si es necesario, puede obtener más información sobre Moq en
https://github.com/moq/moq4/wiki.

Para simplificar el caso de prueba unitaria, marqué con comentarios las líneas
del código que lee los datos desde los parámetros Post hasta el método Run de
HTTPTriggerCSharpFromVS HTTPTrigger, como se muestra abajo, resaltado
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

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Para crear el nuevo proyecto de prueba unitaria, haga clic derecho en la


solución y luego haga clic en Add New Project. En la ventana Add New
Project, elija Test en la lista de Project Type y seleccione xUnit Test Project
(.NET Core) en la lista de proyectos, como se detalla aquí:

2. Asegúrese de elegir xUnit Test Project(.NET Core) en la consola Package


Manager y ejecute estos comandos:
°° Instale el paquete de NuGet de Moq utilizando el comando Install-
Package Moq
°° Instale el paquete ASP.NET Core utilizando el comando Install-
Package Microsoft.AspNetCore
3. En el proyecto de prueba unitaria, también necesitamos la referencia a la
función de Azure donde queremos ejecutar las pruebas unitarias. Añada una
referencia a la aplicación FunctionAppInVisualStudio para poder solicitar
el método Run del desencadenador HTTP desde nuestras pruebas unitarias.

[ 155 ]
Explorar las herramientas de prueba para validar las funciones de Azure

4. Agregue todos los espacios de nombres necesarios a la clase Unit Test,


como se explica más abajo, y reemplace el código predeterminado por el
siguiente código. Este código simula las solicitudes, crea una colección
de cadenas de consultas con una clave denominada name, asigna el valor
Praveen Sreeram, ejecuta la función, obtiene la respuesta y luego compara
el valor de respuesta con el 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. Ahora, haga clic derecho en la prueba unitaria y luego haga clic en Run
test(s), como se muestra en esta captura de pantalla:

Si todo está configurado correctamente, las pruebas serán exitosas, como vemos aquí:

Eso es todo. Hemos aprendido a escribir un caso de prueba unitaria básica para un
desencadenador HTTP.

[ 157 ]
Supervisar y solucionar
problemas en los servicios
sin servidor de Azure
En este capítulo, aprenderá a hacer lo siguiente:

• Solución de problemas relacionados con las funciones de Azure.


• Integración de las funciones de Azure con Application Insights.
• Supervisión de las funciones de Azure.
• Inserción de detalles de telemetría personalizados en Application
Insights Analytics.
• Envío de detalles de telemetría de aplicación por correo electrónico.
• Integración datos de supervisión de Application Insights en tiempo real con
Power BI utilizando Azure Functions.

Introducción
Completar el desarrollo de un proyecto y activar una aplicación no es el final de
la historia de implementación. Necesitamos supervisar continuamente nuestras
aplicaciones, analizar su rendimiento y revisar sus registros para entender si los
usuarios finales se están enfrentando a algún problema.

Azure nos proporciona varias herramientas para satisfacer todos nuestros requisitos
de supervisión, directamente desde las fases de desarrollo y mantenimiento.

En este capítulo, aprenderá a utilizar estas herramientas y a tomar las medidas


necesarias en función de la información disponible.

[ 158 ]
Capítulo 6

Solución de problemas relacionados con


las funciones de Azure
En esta tarea, aprenderá a consultar los registros de aplicaciones de sus aplicaciones
de función utilizando la característica de transmisión de registros de las funciones.

Procedimiento...
Una vez que haya terminado con el desarrollo y que haya probado sus aplicaciones
exhaustivamente en el entorno local, puede intentar implementarlas en Azure.
A veces, suelen surgir ciertos problemas después de implementar una aplicación en
Azure, ya que el entorno es diferente. Por ejemplo, el desarrollador podría haberse
olvidado de crear App Settings en la aplicación. Si falta una clave de configuración,
la aplicación podría no funcionar como se esperaba y no es fácil solucionar el error.
Afortunadamente, el entorno de Azure facilita la tarea con la característica
de transmisión de registros. En esta tarea, aprenderemos a consultar registros en
tiempo real y también entenderemos cómo utilizar la característica Diagnose and
solve problems.

Consultar registros de aplicaciones en tiempo real


Lleve a cabo los pasos siguientes:
1. Diríjase a Platform features en la aplicación de función y haga clic en
el botón Log Streaming para consultar los registros de aplicaciones en
Application logs, como se ve en la siguiente captura de pantalla:

En el momento de la redacción de este libro, los registros del


servidor web no proporcionan ningún tipo de información
relacionada con Azure Functions.

[ 159 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

2. Abramos cualquiera de las funciones de Azure que agregó anteriormente


en una nueva pestaña de explorador y agreguemos una línea de código que
produzca una excepción. Para simplificarlo (y solo ilustrar cómo los registros
de aplicaciones funcionan en la transmisión de registro), agregué la línea
siguiente al desencadenador HTTP simple que creé antes:

3. Luego haga clic en el botón Save y, después, en el botón Run. Como


se esperaba, recibirá una excepción junto con el mensaje en la sección
Application logs que se muestra en esta captura de pantalla:

En la ventana de registro se muestran los errores solo para esa función


en particular y no para las otras funciones asociadas con la aplicación de
función. Por esto son útiles los registros de aplicaciones de transmisión
de registros, que se pueden utilizar en todas las funciones de cualquier
aplicación de función.

[ 160 ]
Capítulo 6

Diagnosticar toda la aplicación de función


En la sección anterior, aprendimos a supervisar los errores de aplicaciones en tiempo
real, lo cual nos puede servir para identificar y solucionar al instante cualquier error
que encontremos. Sin embargo, no siempre es posible supervisar los registros de
aplicación y comprender los errores con los que tienen que lidiar los usuarios finales.
Azure Functions ofrece otra herramienta maravillosa, denominada Diagnose and
solve problems:
1. Desplácese a Platform features y haga clic en Diagnose and solve problems,
como vemos aquí:

2. En un instante, el sistema lo dirigirá a otra hoja, donde podrá elegir la


categoría adecuada para los problemas que está intentando resolver. Haga
clic en 5xx Errors para ver los detalles de las excepciones que se les presentan
a los usuarios finales, como se observa en la siguiente captura de pantalla:

[ 161 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

3. Como resultado, verá los campos Function Availability and Performance


y Application Crashes. Haga clic en la opción Function Availability and
Performance para ver los enlaces reales, como se muestra aquí:

4. Haga clic en Function Executions and Errors para consultar las excepciones
detalladas, como se ve en la siguiente captura de pantalla:

Aún hay más...


Cada evento de función se registra en el servicio de Almacenamiento de tablas de
Azure. Una vez al mes, se crea una tabla con el nombre AzureWebJobsHostLogs
<Year><Month>.

[ 162 ]
Capítulo 6

Como parte de la solución de problemas, si desea conocer más detalles sobre algún
error, debe buscar el campo Id en la sección Invocation details, como se muestra en
la siguiente captura de pantalla:

Busque esos datos en la columna RowKey de la tabla AzureWebJobsHostLogs


<year><month>, como figura aquí:

Como se muestra en la captura de pantalla anterior, obtendrá la entrada de registro


guardada en el almacenamiento de tablas. Al hacer clic en la fila, se abren los detalles
completos del error, como se muestra aquí:

[ 163 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

Integración de las funciones de Azure


con Application Insights
Application Insights es un servicio de administración del rendimiento de
aplicaciones. Una vez que integre Application Insights en su aplicación, empezará
a enviar datos de telemetría a su cuenta de Application Insights hospedada en
la nube. En esta tarea, aprenderá lo sencillo que es integrar Azure Functions con
Application Insights.

Preparación
Creamos una cuenta de Application Insights en la tarea Probar y validar la capacidad de
respuesta de las funciones de Azure utilizando Application Insights del Capítulo 5, Explorar
las herramientas de prueba para validar las funciones de Azure. Cree una cuenta, si aún no
lo ha hecho, siguiendo estos pasos:

1. Diríjase al portal de administración de Azure, haga clic en Create a resource


y luego seleccione Management Tools.
2. Elija Application Insights y brinde todos los detalles solicitados. Si ya ha
creado una cuenta de Application Insights en la tarea anterior, puede omitir
este paso.

[ 164 ]
Capítulo 6

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Después de crear la cuenta de Application Insights, desplácese hasta la


pestaña Overview y diríjase a Instrumentation Key, como se muestra aquí:

2. Diríjase a las aplicaciones de función en Function apps para las que desea
habilitar la supervisión y vaya a Application settings.
3. Agregue una nueva clave con el nombre APPINSIGHTS_INSTRUMENTATIONKEY
e ingrese la clave que copió desde la cuenta de Application Insights, como se
muestra a continuación. Luego haga clic en Save para guardar los cambios.

4. Eso es todo. Ahora puede empezar a utilizar todas las características de


Application Insights para supervisar el rendimiento de las funciones de
Azure. Abra Application Insights y la función RegisterUser en dos
pestañas diferentes para probar cómo trabaja Live Metrics Stream:
°° Abra Application Insights y haga clic en Live Metrics Stream en
la primera pestaña de su explorador, como se ilustra en la siguiente
captura de pantalla:

[ 165 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

°° Abra cualquiera de funciones de Azure (en este caso, abrí el


desencadenador HTTP) en otra pestaña y ejecute algunas
pruebas para asegurarse de que emite algunos registros en
Application Insights.

5. Cuando termine con las pruebas, vaya a la pestaña donde se encuentra


Application Insights. Allí verá el tráfico activo que se dirige a su aplicación
de función, como se muestra aquí:

[ 166 ]
Capítulo 6

Funcionamiento...
Hemos creado una cuenta de Application Insights. Una vez que integre la Clave
de instrumentación de Application Insights con las funciones de Azure, el tiempo
de ejecución se encargará de enviar datos de telemetría de manera asincrónica a su
cuenta de Application Insights.

Aún hay más...


En Live Metrics Stream, también puede consultar todas las instancias, junto con
otros datos, como la cantidad de solicitudes por segundo que manejan las instancias.

Supervisión de las funciones de Azure


Ahora sabemos cómo integrar las funciones de Azure con Application Insights.
A continuación, aprenderemos cómo consultar los registros escritos en Application
Insights mediante el código de las funciones de Azure para que, como desarrollador,
pueda solucionar las excepciones que se produzcan.

Vamos a hacer un pequeño cambio en la función de desencadenador HTTP


y, a continuación, lo ejecutaremos varias veces.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Desplácese hasta el desencadenador HTTP que creó y reemplace el código


siguiente. Acabo de mover la línea de código que registra la información a la
consola Logs y agregué 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 en los servicios sin servidor de Azure

2. Ahora, para ejecutar la función, ingrese un valor en el parámetro name con


diferentes valores, como Azure Test Run 1, Azure Test Run 2 y Azure
Test Run 3. Esto es solo para fines de demostración. Puede utilizar la
entrada que desee. En la consola Logs aparecerá la siguiente salida:

3. Los registros de la consola Logs anterior solo están disponibles si se conecta


con la consola Logs. No los verá si se desconecta. Ahí es donde Application
Insights resulta útil. Vaya a la instancia de Application Insights que integró
con la aplicación de función de Azure.
4. Haga clic en el botón Analytics ubicado en la pestaña Overview de
Application Insights, como se muestra aquí:

[ 168 ]
Capítulo 6

5. En la ventana de consultas de análisis, escriba el comando traces | sort


by timestamp desc, que devuelve todos los seguimientos ordenados por
fecha en orden descendente, como vemos en la siguiente captura de pantalla:

Funcionamiento...
En el desencadenador HTTP, agregamos la instrucción log que muestra el valor
del parámetro name que brinda el usuario. Ejecutamos el desencadenador HTTP
varias veces. Después de unos minutos, haga clic en el botón Analytics en el botón
Application Insights, con lo cual se abrirá la ventana de análisis donde podrá
redactar consultas para ver los datos de telemetría emitidos por Azure Functions.
Puede hacer todo esto sin necesidad de escribir ningún código personalizado.

Inserción de detalles de telemetría


personalizados en Application
Insights Analytics
Nuestros clientes le han pedido que proporcionen informes analíticos para una
métrica derivada dentro de Application Insights. Entonces, ¿qué es una métrica
derivada? De forma predeterminada, Application Insights le proporciona mucha
información sobre métricas, como solicitudes, errores, excepciones, etcétera.

Puede ejecutar consultas en la información que Application Insights ofrece,


utilizando su lenguaje de consulta de Analytics.

[ 169 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

En este contexto, requests per hour es una métrica derivada y, si pretende crear
un nuevo informe dentro de Application Insights, debe brindarle información
a Application Insights sobre la nueva métrica derivada de manera periódica. Una
vez que proporcione los datos requeridos con frecuencia, Application Insights se
encargará de brindar informes para su análisis.

Usaremos las funciones de Azure que brindan a Application Insights una métrica
derivada denominada requests per hour:

En este ejemplo, desarrollaremos una consulta utilizando el lenguaje de consulta


de Analytics para la métrica derivada request per hour. Podemos modificar la
consulta para generar otras métricas derivadas para sus requisitos. Por ejemplo,
requests per hour for my campaign o algo similar.

Puede obtener más información sobre el lenguaje de consulta


de Analytics en https://docs.microsoft.com/en-us/
azure/application-insights/app-insights-
analytics-reference.

[ 170 ]
Capítulo 6

Preparación
Siga estos requisitos previos:

1. Cree una nueva cuenta de Application Insights, si todavía no lo hizo.


2. Asegúrese de tener una aplicación en ejecución que se integre con
Application Insights. Para saber cómo integrar su aplicación con Application
Insights, visite https://docs.microsoft.com/en-us/azure/application-
insights/app-insights-asp-net.

Se recomienda crear esta tarea y las dos tareas posteriores en


una aplicación de función de Azure por separado basada en el
tiempo de ejecución de la v1, ya que estas plantillas todavía no
están disponibles en v2. Por el momento, si no ve la plantilla
Application Insights Scheduled Analytics, cambie la versión
del tiempo de ejecución de las funciones de Azure a v1. Para
esto, tiene que configurar el valor FUNCTIONS_EXTENSIONS_
VERSION en ~1, como se muestra más abajo, en el parámetro
Application settings de Azure Functions:

Procedimiento...
Vamos a seguir estos pasos para insertar detalles de telemetría personalizados en
Application Insights Analytics.
[ 171 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

Crear una función de Application Insights


Lleve a cabo los pasos siguientes:
1. Para crear una plantilla de función nueva, elija Monitoring en el menú
desplegable Scenario, como se observa aquí. También puede buscar
scheduled analytics para hallar la plantilla más fácilmente:

2. Ahora haga clic en C# (que se muestra en la captura de pantalla anterior)


y especifique el nombre junto con la frecuencia de programación a la que
debe ejecutarse la función:

3. Como se muestra en la captura de pantalla anterior, haga clic en el botón


Create para crear la función.
[ 172 ]
Capítulo 6

Configurar claves de acceso


Lleve a cabo los pasos siguientes:

1. Desplácese hasta la hoja Overview de Application Insights, como se muestra,


y copie la clave de instrumentación que figura en Instrumentation Key.
Usaremos la clave de instrumentación para crear una configuración de la
aplicación llamada AI_IKEY en la aplicación de función:

2. Vaya a la hoja API Access y copie el valor ingresado en Application ID.


Vamos a utilizar este valor de Application ID para crear una nueva
configuración de aplicación llamada 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, haga clic en el botón Create API key para generar la nueva
clave de API, como se muestra en la siguiente captura de pantalla. Asigne
un nombre significativo, repase los datos en Read telemetry y haga clic en
Generate key:

[ 173 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

4. Después de unos instantes, podrá ver y copiar la clave, como se ilustra aquí:
Vamos a utilizar esto para crear una nueva configuración de aplicación
llamada AI_APP_KEY en nuestra aplicación de función:

[ 174 ]
Capítulo 6

5. Cree las tres claves de configuración de aplicación en la aplicación de


función, como se detalla más abajo. Utilizaremos estas tres claves en nuestra
función de Azure denominada FeedAIwithCustomDerivedMetric.

Integrar y probar una consulta de


Application Insights
Lleve a cabo los pasos siguientes:

1. Ahora vamos a desarrollar una consulta que nos proporcione el valor de


la métrica derivada requests per hour. Diríjase a la hoja Overview de
Application Insights y haga clic en el botón Analytics.
2. El sistema lo llevará a la hoja Analytics. Escriba la siguiente consulta en la
pestaña de consulta. Puede redactar su propia consulta según sus requisitos.
Asegúrese de que la consulta arroje un valor escalar:
requests
| where timestamp > now(-1h)
| summarize count()

3. Cuando termine con la consulta, ejecútela haciendo clic en el botón Run para
ver la cantidad de registros, como se muestra en esta captura de pantalla:

[ 175 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

4. Ya preparamos la consulta de Application Insights requerida.


A continuación, vamos a integrar la consulta con nuestra función
FeedAIwithCustomDerivedMetrics. Desplácese hasta el editor de código
de Azure Functions y realice los siguientes cambios:
1. Especifique un nombre significativo para la métrica derivada. En este
caso, es Requests per hour.
2. Reemplace la consulta predeterminada por la que acabamos
de desarrollar.
3. Para guardar los cambios, haga clic en el botón Save:

5. Hagamos una prueba rápida para comprobar si configuró las tres


configuraciones de aplicación y la consulta de forma correcta. Diríjase a la
pestaña Integrate y modifique la frecuencia de ejecución a un minuto, como
vemos en esta captura de pantalla:

[ 176 ]
Capítulo 6

6. Ahora consultemos la pestaña Monitor para ver si todo funciona bien. Si


hay algún problema, aparecerá una X en la columna Status. Visualice el
error en la sección Logs en la pestaña Monitor haciendo clic en la entrada
Invocation log:

7. Después de comprobar que la función se esté ejecutando sin inconvenientes,


revierta la frecuencia de Schedule a una hora.

Configurar el informe de una métrica


derivada personalizada
Lleve a cabo los pasos siguientes:

1. Diríjase a la pestaña Overview de Application Insights y haga clic en el menú


Metrics, como se muestra abajo:

2. Metrics Explorer sirve para hallar todos los análisis relacionados con las
diferentes métricas. En Metrics Explorer, haga clic en el botón Edit de
cualquier informe para configurar la métrica personalizada, como se observa
aquí (o haga clic en el botón Add chart en el extremo superior izquierdo de la
siguiente captura de pantalla):

[ 177 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

3. Luego, el sistema lo llevará a la hoja Chart details, donde puede configurar la


métrica personalizada y demás detalles asociados con el gráfico. En el menú
desplegable METRIC NAMESPACE, elija azure.applicationinsghts, como
figura abajo, y luego seleccione la métrica personalizada Request per hour
que creó:

[ 178 ]
Capítulo 6

4. Posteriormente, se creará el gráfico como se muestra en la siguiente captura


de pantalla:

Funcionamiento...
El proceso completo funciona de esta manera:

• Creamos la función de Azure utilizando la plantilla predeterminada


Application Insights Scheduled Analytics.
• Configuramos las siguientes claves en Application settings de la aplicación
de función de Azure:
°° Instrumentation Key de Application Insights.
°° La ID de la aplicación.
°° La clave de acceso de la API.

• El tiempo de ejecución de la función de Azure consumió automáticamente la


API de Application Insights, ejecutó la consulta personalizada para recuperar
las métricas necesarias y realizó las operaciones necesarias para alimentar los
datos de telemetría derivados a Application Insights.

[ 179 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

• Una vez que se configuró todo en la función de Azure, desarrollamos una


consulta simple que extrajo el recuento de solicitudes de la última hora y lo
alimentó en Application Insights como una métrica derivada personalizada.
Este proceso se repitió cada hora.
• Luego configuramos un informe nuevo utilizando Application Insights
Metrics con nuestra métrica derivada personalizada.

Envío de detalles de telemetría de


aplicación por correo electrónico
Una de las actividades de su aplicación, cuando esté activa, será recibir un correo
electrónico de notificación con los detalles sobre el estado, los errores, el tiempo de
respuesta, entre otros, con una frecuencia mínima de una vez al día.

Azure Functions nos ofrece la capacidad de obtener todos los detalles básicos
utilizando una plantilla de función con código que se encarga de recuperar todos los
valores necesarios de Application Insights y un código "plumbing" para enmarcar
el cuerpo del correo electrónico y enviar el correo electrónico a través de SendGrid.
Veremos cómo hacerlo en esta tarea.

Preparación
Siga estos requisitos previos:

1. Cree una nueva cuenta de SendGrid, si aún no ha creado una, y obtenga la


clave de la API de SendGrid.
2. Cree una nueva cuenta de Application Insights, si todavía no lo hizo.
3. Asegúrese de tener una aplicación en ejecución que se integre con
Application Insights.

Para saber cómo integrar su aplicación con Application Insights, visite


https://docs.microsoft.com/en-us/azure/application-
insights/app-insights-asp-net.

[ 180 ]
Capítulo 6

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva función. Para ello, elija Monitoring en el menú desplegable
Scenario y seleccione la plantilla Application Insights scheduled
digest—C#, como se muestra aquí:

2. Después de unos instantes, el sistema le pedirá que especifique el nombre de


la función, la frecuencia programada y la clave de la API de SendGrid para
el enlace de salida de SendGrid, como se observa a continuación:

[ 181 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

3. Luego haga clic en el botón Create que figura en el paso anterior para crear la
nueva función de Azure. La plantilla crea el código necesario para consultar
los datos de Application Insights y envía un correo electrónico a la persona
mencionada en To address de la captura de pantalla anterior.

Asegúrese de seguir los pasos de la sección Configuring access keys de


la tarea Pushing custom telemetry details to analytics of Application
Insights para configurar estas claves de acceso: clave de instrumentación
de Application Insights, la ID de la aplicación y la clave de acceso
de la API.

4. Diríjase a la función run.csx y cambie el nombre de la aplicación por el


nombre de su aplicación, como se ve a continuación:

5. Si configuró todos los ajustes correctamente, comenzará a recibir correos


electrónicos basados en la configuración del temporizador.
6. Hagamos una prueba rápida. Para ello, haga clic en el botón Run ubicado
arriba del editor de código, como se ilustra en esta captura de pantalla:

7. Esta es la captura de pantalla del correo electrónico que recibí después de


hacer clic en el botón Run en el paso anterior:

[ 182 ]
Capítulo 6

Funcionamiento...
La función de Azure emplea la API de Application Insights para ejecutar todas las
consultas de Application Insights Analytics, recupera cada uno de los resultados,
enmarca el cuerpo del correo electrónico con todos los detalles e invoca la
API de SendGrid para enviar un correo electrónico a la cuenta de correo
electrónico configurada.

Aún hay más...


Las plantillas de Azure proporcionan un código predeterminado con algunas
consultas que suelen ser útiles para supervisar el estado de las aplicaciones. Si tiene
requisitos específicos para recibir alertas de notificación, agregue nuevas consultas al
método GetQueryString. Para incorporar los valores nuevos, debe cambiar la clase
DigestResult y la función GetHtmlContentValue.

Consulte también
La tarea Enviar una notificación por correo electrónico al administrador de un sitio web
utilizando el servicio SendGrid del Capítulo 2, Trabajar con notificaciones utilizando los
servicios SendGrid y Twilio.

Integración de datos de supervisión de


Application Insights en tiempo real con
Power BI utilizando Azure Functions
A veces, tendrá que consultar datos en tiempo real sobre la disponibilidad de su
aplicación o información relacionada con el estado de la misma en un sitio web
personalizado. Recuperar información para Application Insights y mostrarla en un
informe personalizado sería un trabajo tedioso, ya que necesitaría desarrollar un sitio
web independiente y compilarlo, probarlo y alojarlo en algún lugar.

En esta tarea, aprenderá lo fácil que es consultar información de estado en tiempo


real para la aplicación mediante la integración de Application Insights y Power BI.
Vamos a aprovechar las capacidades de Power BI para transmisión de dato en vivo
y las funciones de temporizador de Azure para brindar continuamente la
información de estado a Power BI. Este es un diagrama de alto nivel donde se
ilustra lo que haremos durante el resto de esta tarea:

[ 183 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

En esta tarea, utilizaremos la plantilla Application Insights Power BI


de una aplicación de función creada utilizando el tiempo de ejecución
de las funciones de Azure v1. El tiempo de ejecución de las funciones
de Azure v2 no lo tiene. Si está utilizando el tiempo de ejecución de
la v2, puede crear un desencadenador de temporizador y seguir las
instrucciones de esta tarea.

Preparación
Siga estos requisitos previos:

1. Cree una cuenta de Power BI en https://powerbi.microsoft.com/.


2. Cree una nueva cuenta de Application Insights, si todavía no lo hizo.
3. Asegúrese de tener una aplicación en ejecución que se integre con
Application Insights. Para saber cómo integrar su aplicación con Application
Insights, visite https://docs.microsoft.com/en-us/azure/application-
insights/app-insights-asp-net.

[ 184 ]
Capítulo 6

Debe utilizar su cuenta de trabajo para crear una cuenta de Power BI. En
el momento de la redacción de este libro, no es posible crear una cuenta
de Power BI con una dirección de correo electrónico personal como
Gmail, Yahoo y demás.
Asegúrese de seguir los pasos de la sección Configuring access keys de
la tarea Pushing custom telemetry details to analytics of Application
Insights para configurar estas claves de acceso: clave de instrumentación
de Application Insights, la ID de la aplicación y la clave de acceso
de la API.

Procedimiento...
Llevaremos a cabo los pasos siguientes para integrar Application Insights
y Power BI.

Configurar Power BI con un panel, un conjunto de


datos y una URL de inserción
Lleve a cabo los pasos siguientes:

1. Si es la primera vez que utiliza el portal de Power BI, haga clic en Skip en la
página de bienvenida, como se muestra aquí:

[ 185 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

2. El próximo paso es crear un conjunto de datos de streaming en Create


y luego seleccionar Streaming dataset, como figura aquí:

3. En el paso New streaming dataset, elija API y haga clic en el botón Next,
como se muestra en la siguiente captura de pantalla:

[ 186 ]
Capítulo 6

4. En el siguiente paso, vamos a crear los campos para el conjunto de datos de


streaming. Proporcione un nombre significativo para el conjunto de datos
e indique los valores que le gustaría insertar en Power BI. Para esta tarea,
creé un conjunto de datos con solo un campo, llamado RequestsPerSecond,
del tipo Number e hice clic en Create, como se muestra aquí:

5. Después de crear el conjunto de datos, el sistema le pedirá que complete el


campo Push URL, como vemos más abajo. Vamos a utilizar esta URL de
inserción en Azure Functions para insertar los datos RequestsPerSecond
cada segundo (o según sus requisitos) con el valor real de las solicitudes por
segundo. Haga clic en Done:

[ 187 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

6. El siguiente paso es crear un panel que contenga un mosaico. Para crear un


nuevo panel, haga clic en Create y elija Dashboard, como se muestra aquí:

[ 188 ]
Capítulo 6

7. En la ventana emergente Create dashboard, especifique un nombre


significativo y haga clic en Create, como se ilustra más abajo, para crear un
panel vacío:

8. En el panel vacío, haga clic en el botón Add tile para crear un mosaico nuevo.
Al hacer clic en Add tile, se abrirá otra ventana emergente, donde puede
seleccionar el origen de datos desde el cual se rellenará el mosaico:

[ 189 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

9. Seleccione Custom Streaming Data y haga clic en Next, como se muestra en


la captura de pantalla anterior. En el siguiente paso, seleccione el conjunto
de datos Requests y haga clic en el botón Next:

10. Luego elija el tipo de visualización en Visualization Type (que en este caso
es Card) y seleccione los campos desde el origen de datos, como vemos en
esta captura de pantalla:

11. El último paso es asignarle un nombre al mosaico. En este caso, lo llamé


RequestsPerSecond. Es posible que este nombre no tenga sentido aquí, pero
usted puede especificar el nombre que desee según sus 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, siga estos pasos:

1. Diríjase a Azure Functions y cree una nueva función empleando la


siguiente plantilla:

2. En la captura de pantalla anterior, haga clic en C# para especificar un


nombre en Name y haga clic en el botón Create, como se ilustra aquí:

[ 191 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

3. Reemplace el código predeterminado por el siguiente. Asegúrese de


configurar el valor correcto del que la consulta de análisis debe extraer los
datos. En este caso, indiqué cinco minutos (5m) en el código a continuación:
#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 según la frecuencia de temporizador que haya configurado.

[ 193 ]
Supervisar y solucionar problemas en los servicios sin servidor de Azure

4. En esta captura de pantalla hay una secuencia de imágenes que muestran los
datos en tiempo real:

Funcionamiento...
Hemos creado lo siguiente en este orden específico:

1. Un conjunto de datos de streaming en la aplicación Power BI.


2. Un panel y un nuevo mosaico donde se muestran los valores disponibles en
el conjunto de datos de streaming.
3. Una nueva función de Azure que ejecuta una consulta de Application
Insights Analytics y envía los datos a Power BI utilizando la dirección URL
de inserción del conjunto de datos.
4. Una vez que todo está hecho, podemos ver los datos en tiempo real en el
mosaico de Power BI del tablero.

Aún hay más...


• Power BI nos permite crear datos en tiempo real en informes de varias
maneras. En esta tarea, aprendió a crear informes en tiempo real utilizando
el conjunto de datos de streaming. Las demás alternativas son con el conjunto
de datos de inserción y el conjunto de datos de streaming de PubNub.
Puede obtener más información sobre los tres enfoques en
https://powerbi.microsoft.com/documentation/powerbi-service-
real-time-streaming/.
• Tenga mucho cuidado si opta por los datos de estado de aplicaciones en
tiempo real. La API de Application Insights tiene un límite de frecuencia.
Consulte https://dev.applicationinsights.io/documentation/
Authorization/Rate-limits para obtener más información sobre los
límites de la API.

[ 194 ]
Desarrollar aplicaciones
sin servidor fiables con
Durable Functions
En este capítulo, aprenderá a hacer lo siguiente:

• Configuración de Durable Functions en el portal de administración de Azure.


• Creación de una aplicación HelloWorld para Durable Functions.
• Prueba y solución de problemas en Durable Functions.
• Implementación de aplicaciones fiables multiprocesos con Durable Functions.

Introducción
Durante las tareas de desarrollo de aplicaciones modernas que deben hospedarse en
la nube, conviene asegurarse de que las aplicaciones no tengan estado. Esta carencia
de estado es un factor esencial para desarrollar aplicaciones habilitadas para la
nube. Por ejemplo, conviene evitar conservar en el recurso aquellos datos específicos
de una instancia de máquina virtual (VM) aprovisionada en cualquier servicio
de Azure (por ejemplo, el servicio de aplicaciones, la API, etcétera). De lo contrario,
no podrá aprovechar algunos de los servicios, como la funcionalidad de escalado
automático, ya que el aprovisionamiento de instancias es dinámico. Si depende
de los recursos específicos de una máquina virtual, terminará enfrentando problemas
por comportamientos inesperados.

Por otro lado, la desventaja del enfoque mencionado más arriba es que termina
trabajando para identificar las posibles formas de conservar datos en diferentes
medios, dependiendo de la arquitectura de la aplicación.

[ 195 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

Para obtener más información sobre Durable Functions, consulte la


documentación oficial disponible en https://docs.microsoft.com/
en-us/azure/azure-functions/durable-functions-overview.

Configuración de Durable Functions


en el portal de administración de Azure
Azure descubrió una nueva forma de administrar el rasgo del estado en la
arquitectura sin servidor, junto con otras características como la durabilidad
y la fiabilidad, mediante Durable Functions. Este servicio está disponible como una
extensión de Azure Functions. En este capítulo, aprenderemos conceptos básicos
sobre Durable Functions.

Preparación
Cree una nueva aplicación de función, si aún no lo hizo. Verifique que la versión del
tiempo de ejecución sea ~2 en Application settings, como se muestra en esta captura
de pantalla:

[ 196 ]
Capítulo 7

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Haga clic en el botón + para crear la nueva función:

2. Para crear la nueva función Durable Functions HTTP starter, elija


Durable Functions en el menú desplegable Scenario, como se ve aquí:

3. A continuación, se abrirá una nueva pestaña:

[ 197 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

4. Haga clic en el botón Install, que se muestra en el paso anterior, para


empezar a instalar las extensiones DurableTask. La instalación de las
dependencias tarda alrededor de dos minutos:

5. Una vez finalizado el proceso, aparecerá lo siguiente:

Aún hay más...


Actualmente, C# es el único lenguaje compatible para desarrollar Durable Functions.
La compatibilidad con otros lenguajes se detalla en la fase de vista previa.

[ 198 ]
Capítulo 7

Creación de una aplicación HelloWorld


para Durable Function
Aunque el propósito general de este libro es que cada una de las tareas de cada
capítulo resuelva al menos un problema comercial, esta tarea no ayuda a resolver
ningún problema de dominio en tiempo real. En cambio, proporciona algunas
instrucciones de inicio rápido para ayudarle a conocer en detalle Durable Functions
y sus componentes, junto con el enfoque de desarrollo de Durable Functions. En el
siguiente capítulo, veremos qué sencillo es desarrollar una aplicación basada en el
flujo de trabajo utilizando Durable Functions.

Preparación
Antes de continuar, llevaremos a cabo los pasos siguientes:

1. Descargue e instale Postman desde https://www.getpostman.com/ si es


necesario
2. Conozca más sobre Orchestrator y los enlaces de desencadenador
de actividad en https://docs.microsoft.com/en-us/azure/
azure-functions/durable-functions-bindings

Procedimiento...
Para desarrollar Durable Functions, tenemos que crear estas tres funciones:

• Cliente de Orchestrator: una función de Azure capaz de administrar


instancias de Orchestrator.
• Función de Orchestrator: la función real de Orchestrator permite desarrollar
flujos de trabajo con estado mediante un código. Esta función puede llamar,
de manera asincrónica, a otras funciones de Azure (llamadas Funciones de
actividad), e incluso puede guardar los valores devueltos de esas funciones
en variables locales.
• Funciones de actividad: estas son las funciones a las que llamarán las
funciones de Orchestrator.

[ 199 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

Crear la función HttpStart en el cliente de Orchestrator


Lleve a cabo los pasos siguientes:

1. Cree una nueva función de inicio HTTP de Durable Functions eligiendo


Durable Functions en el menú desplegable Scenario y luego haga clic en
Durable Functions HTTP starter, con lo cual se abrirá una nueva pestaña,
como se muestra aquí. Crearemos una nueva función HTTP denominada
HttpStart:

2. A continuación, el sistema lo llevará al editor de código. La siguiente función


es un desencadenador HTTP que acepta el nombre de la función que debe
ejecutarse junto con la entrada. Emplea 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,

[ 200 ]
Capítulo 7

eventData);

log.LogInformation($"Started orchestration with ID =


'{instanceId}'.");

return starter.CreateCheckStatusResponse(req,
instanceId);
}

3. Diríjase a la pestaña Integrate y haga clic en Advanced editor, como


se ilustra aquí:

4. En Advanced editor, deben aparecer enlaces similares a los siguientes. De lo


contrario, reemplace el código predeterminado por el siguiente:
{
"bindings":
[
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": [
"post",
"get"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",

[ 201 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

"type": "orchestrationClient",
"direction": "in"
}
]
}

La función HttpStart funciona como una gateway para invocar todas


las funciones en la aplicación de función. Todas las solicitudes que haga
empleando el formato de URL https://<durablefunctionname>>.
azurewebsites.net/api/orchestrators/{functionName}
llegarán a la función HttpStart. Esta función se encargará de ejecutar la
función Orchestrator, según el parámetro disponible en el parámetro
de ruta {functionName}. Todo esto es posible gracias al atributo
route, definido en function.json de la función HttpStart.

Crear la función de Orchestrator


Lleve a cabo los pasos siguientes:

1. Crearemos una función de Orchestrator. Para ello, haga clic en la plantilla


Durable Functions orchestrator, que se muestra de esta manera:

2. Después de hacer clic en el mosaico Durable Functions orchestrator,


el sistema lo dirigirá a la siguiente pestaña donde tiene que brindar
el nombre de la función. Una vez que especifique el nombre, haga clic
en el botón Create para crear la función de Orchestrator:

[ 202 ]
Capítulo 7

3. En DurableFuncManager, reemplace el código predeterminado por lo


siguiente y haga clic en el botón Save para guardar los cambios: este
orquestador solicitará las funciones de actividad a través del 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 Integrate, reemplace el código


predeterminado por el siguiente:
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}

[ 203 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

Crear una función de actividad


Lleve a cabo los pasos siguientes:

1. Cree una nueva función denominada ConveyGreeting utilizando la plantilla


Durable Functions activity:

2. Reemplace el código predeterminado por el siguiente código, que solo


muestra el nombre especificado como entrada, y haga clic en el botón
Save 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 Integrate, reemplace el código


predeterminado por el siguiente:
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
]
}

En esta tarea, acabamos de crear un cliente de orquestación, una función de


Orchestrator y una función de actividad. Aprenderemos cómo probar todo esto en la
próxima tarea.

[ 204 ]
Capítulo 7

Funcionamiento
Echemos un vistazo al trabajo realizado en esta tarea:

• Primero desarrollamos el cliente de Orchestrator (en este caso, HttpStart),


que puede crear orquestadores empleando la función StartNewAsync de la
clase DurableOrchestrationClient. Este método permite crear una nueva
instancia de Orchestrator.
• Luego desarrollamos la función de Orchestrator, es decir, la parte primordial
de Durable Functions. Estas son algunas de las características principales más
importantes del contexto de Orchestrator:
°° Puede invocar varias funciones de actividad.
°° Puede guardar la salida que una función de actividad devuelve y
pasarla a otra función de actividad.
°° Estas funciones de Orchestrator también pueden crear puntos de
control que guardan puntos de ejecución, de modo que si hay algún
problema con las máquinas virtuales, puede 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 de negocios. En nuestro caso, solo se vuelve un
simple mensaje.

Aún hay más...


Durable Functions depende de Durable Task Framework. Para conocer más
información sobre Durable Task Framework, visite https://github.com/Azure/
durabletask.

Prueba y solución de problemas


en Durable Functions
En los capítulos anteriores, analizamos diferentes formas de probar las funciones
de Azure. Podemos probar Durable Functions con las mismas herramientas. Sin
embargo, el enfoque de las pruebas es completamente diferente debido
a sus características y a la forma en que funciona.

En esta tarea, aprenderemos algunas cosas fundamentales que se deben tener


en cuenta al trabajar con Durable Functions.

[ 205 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

Preparación
Descargue e instale lo siguiente, si aún no ha hecho:

• La herramienta Postman, disponible en https://www.getpostman.com.


• El explorador de Microsoft Azure Storage, disponible en
http://storageexplorer.com.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Navegue hasta el editor de código de la función HttpStart y obtenga la


URL haciendo clic en </>Get function URL. Reemplace el valor de plantilla
{functionName} por DurableFuncManager.
2. Hagamos una solicitud POST utilizando Postman:

3. Después de hacer clic en el botón Send, recibirá 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. Haga clic en statusQueryGetUri en el paso anterior para consultar el estado


de la función. Al hacer clic en el enlace en el paso anterior, se abre la consulta
en una nueva pestaña en la herramienta Postman. Con la nueva pestaña
abierta, haga clic en el botón Send para obtener la salida real:

[ 206 ]
Capítulo 7

5. Si todo se realizó correctamente, veremos runtimeStatus como Completed


en Postman, como se muestra en la captura de pantalla anterior. También
verá ocho registros en el almacenamiento de tabla, donde se almacena el
historial de ejecución, como figura aquí:

6. Si algo salió mal, aparecerá el mensaje de error en la columna de resultados,


que le indicará la función en la que se produjo el error. Si ese es el caso,
diríjase a la pestaña Monitor de esa función para consultar una explicación
detallada del error.

[ 207 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

Implementación de aplicaciones fiables


multiprocesos con Durable Functions
He trabajado en algunas aplicaciones donde se requiere la ejecución en paralelo
para realizar ciertas tareas de informática. La principal ventaja de este enfoque
es que obtiene la salida deseada bastante rápido, dependiendo de los subprocesos
secundarios que cree. Se puede lograr de muchas 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 secundarios, no es fácil arreglarlo
automáticamente y reanudar desde donde el sistema se detuvo. Estoy seguro de que
muchos de ustedes han enfrentado problemas similares en su aplicación, ya que es
un caso empresarial muy habitual.

En esta tarea, 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 acercaron a nosotros para generar un gran número de códigos de barras
(por ejemplo, alrededor de 50.000). Se necesitaría mucho tiempo para generar los
códigos de barras, ya que implicaría realizar algunas tareas de procesamiento de
imágenes. Por lo tanto, una manera sencilla de procesar con velocidad la solicitud
es utilizar la programación asincrónica, para la cual creamos un proceso por cliente
y luego ejecutamos la lógica en paralelo para cada uno de ellos.

También simularemos un caso de uso simple para entender cómo Durable Functions
se repara automáticamente cuando la máquina virtual en la que se hospeda se apaga
o se reinicia.

Preparación
Instale lo siguiente, si aún no ha hecho:

• La herramienta Postman, disponible en https://www.getpostman.com/.


• El explorador de Microsoft Azure Storage, disponible en
http://storageexplorer.com/.

[ 208 ]
Capítulo 7

Procedimiento...
En esta tarea, vamos a crear los siguientes desencadenadores de funciones de Azure:

• Una función de Orchestrator llamada GenerateBARCode.


• Dos funciones de desencadenador de actividad, que se detallan aquí:
°° GetAllCustomers: para simplificar la tarea, esta función tan solo
devuelve el conjunto de los ID de clientes. En las aplicaciones reales,
hay una lógica de negocios que decide qué clientes son elegibles
y, en base a esto, se devuelven los ID de clientes elegibles.
°° CreateBARCodeImagesPerCustomer: en realidad, esta función no
crea el código de barras, sino que registra un mensaje en la consola,
ya que nuestro objetivo es comprender las características de Durable
Functions. Para cada cliente, generaremos, de forma aleatoria, una
cantidad menor a 50.000 y simplemente iteraremos a través de ella.

Crear la función de Orchestrator


Lleve a cabo los pasos siguientes:

1. Cree una nueva función llamada GenerateBARCode utilizando la


plantilla Durable Functions Orchestrator template. Reemplace el código
predeterminado por el siguiente y haga clic en el botón Save para guardar
los cambios. Al comienzo, el siguiente código clasifica la función de actividad
GetAllCustomers, almacena todos los ID de clientes en una matriz y luego,
para cada cliente, vuelve a recuperar otra función de actividad que
devuelve la cantidad de códigos de barras generados. Por último, espera
hasta que se completen las funciones de actividad para todos los clientes
y, a continuación, devuelve la suma de todos los códigos de barras generados
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]);

[ 209 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

await Task.WhenAll(tasks);
int nTotalItems = tasks.Sum(item => item.Result);

return nTotalItems;
}

2. En el Editor avanzado de la pestaña Integrate, reemplace el código


predeterminado por el siguiente:
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}

Crear la función de actividad GetAllCustomers


Lleve a cabo los pasos siguientes:

1. Cree una nueva función llamada GetAllCustomers utilizando la plantilla


Durable Functions Activity template, reemplace el código predeterminado
por el siguiente y haga clic en el botón Save 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 Integrate, reemplace el código


predeterminado por el siguiente:
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",

[ 210 ]
Capítulo 7

"direction": "in"
}
]
}

Crear la función de actividad


CreateBARCodeImagesPerCustomer
Lleve a cabo los pasos siguientes:

1. Cree una nueva función llamada CreateBARCodeImagesPerCustomer


utilizando la plantilla Durable Functions Activity template. Reemplace el
código predeterminado por el siguiente y haga clic en el botón Save 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 Integrate, reemplace el código
predeterminado por el siguiente:
{
"bindings": [
{
"name": "customerContext",
"type": "activityTrigger",
"direction": "in"
}
]
}

[ 211 ]
Desarrollar aplicaciones sin servidor fiables con Durable Functions

3. Ejecutaremos la función a través de Postman. Detendremos App Service para


simular el reinicio de la VM donde se ejecutará la función y para ver cómo se
reanuda Durable Function desde donde se detuvo.
4. Realice una solicitud POST utilizando Postman, como se muestra aquí:

5. Después de hacer clic en el botón Send, recibirá una respuesta con la URL
de estado. Haga clic en statusQueryGetURi para ver el estado de la función.
Al hacer clic en el enlace statusQueryGetURi, se abrirá en una nueva
pestaña dentro de la herramienta Postman. Cuando la nueva pestaña se abra,
haga clic en el botón Send para consultar el progreso de la función.
6. Mientras la función se ejecuta, diríjase a la hoja Overview de la aplicación
de función y detenga el servicio haciendo clic en el botón Stop:

7. La ejecución de la función se detendrá en la mitad. Navegue hasta la


cuenta de almacenamiento en el explorador de Storage y abra la tabla
DurableFunctionsHubHistory para consultar el progreso:

8. Después de un tiempo (en este caso, después de cinco minutos), regrese


a la hoja Overview e inicie el servicio de la aplicación de función. Verá cómo
Durable Function se reanuda desde donde se detuvo. No escribimos ningún
código para esto, sino que es una característica de uso inmediato. Más abajo
se muestra la captura de pantalla de la función terminada:

[ 212 ]
Capítulo 7

Funcionamiento...
Durable Functions nos permite desarrollar una ejecución fiable de nuestras
funciones, lo que significa que incluso si las VM se bloquean o reinician mientras
la función está en ejecución, estas se reanudan de forma automática a su estado
anterior. Esto es gracias a las características llamadas creación de puntos de
comprobación y reproducción, donde el historial de ejecución está almacenado
en la tabla de almacenamiento.

Para conocer más información sobre esta característica, visite


https://docs.microsoft.com/en-us/azure/azure-
functions/durable-functions-checkpointing-and-replay.

Aún hay más...


• Si recibe la respuesta 404 Not Found al ejecutar la URL statusQueryGetURi,
no se preocupe. Tardará algún tiempo, pero finalmente funcionará cuando
realice una solicitud más adelante.
• Para consultar el historial de ejecución de Durable Functions, vaya a la tabla
DurableFunctionsHubHistory, ubicada en la cuenta de almacenamiento
que creó al crear la aplicación de función:

El nombre de la cuenta de almacenamiento se encuentra en Application settings,


como se muestra en la captura de pantalla anterior.

[ 213 ]
Importación masiva de datos
utilizando Azure Durable
Functions y Cosmos DB
En este capítulo, aprenderemos a realizar las siguientes tareas:

• Carga de datos de los empleados en Almacenamiento de blobs.


• Creación de un desencadenador de blobs.
• Creación el orquestador durable y desencadenarlo para cada importación
de Excel.
• Lectura de datos de Excel utilizando funciones de actividad.
• Escalado automático del rendimiento de Cosmos DB.
• Inserción masiva de datos en Cosmos DB.

Introducción
En este capítulo, desarrollaremos un pequeño proyecto. Para ello, nos basaremos en
un caso de uso muy común que resuelve el problema comercial de compartir datos
en diferentes aplicaciones utilizando Excel. Utilizaremos Durable Functions, una
extensión de Azure Functions que le permite escribir flujos de trabajo escribiendo las
líneas mínimas de código.

[ 215 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

Estas son las dos características principales de Durable Functions que vamos
a utilizar en las tareas de este capítulo:

• Orchestrator: esta función se encarga de administrar todos los


desencadenadores de actividad. Se puede tratar como un administrador
de flujos de trabajo que posee varios pasos. Orchestrator inicia el
desencadenador de actividad, pasa entradas al desencadenador de
actividad, obtiene la salida, mantiene el estado y luego pasa la salida
de un desencadenador de actividad a otro, si es necesario.
• Desencadenador de actividad: cada desencadenador de actividad se puede
tratar como un paso del flujo de trabajo que realiza una función.

Para conocer más información sobre Durable Functions, visite


https://docs.microsoft.com/en-us/azure/azure-
functions/durable-functions-overview.

Problema comercial
En general, cada organización utilizará varias aplicaciones hospedadas en diversas
plataformas en distintos centros de datos (ya sea en la nube o en las instalaciones).
A menudo, nos encontramos con ciertos requisitos que exigen transmitir los datos de
una aplicación a otro sistema. Para exportar datos de una aplicación e importarlos
a otra, se suelen emplear hojas de cálculo de Excel (o, en algunos casos, archivos
JSON o XML).

Podríamos pensar que exportar un archivo de Excel de una aplicación a otra es


un trabajo sencillo. Sin embargo, si tenemos muchas aplicaciones que necesitan
transmitir datos a otras, con una frecuencia semanal o mensual, sería una tarea muy
tediosa con mucho margen para errores manuales. Por lo tanto, está claro que la
solución es automatizar el proceso en la mayor medida posible.

En este capítulo, aprenderemos a desarrollar una solución duradera basada en


la arquitectura sin servidor utilizando Durable Functions. Si leyó el Capítulo 7,
Desarrollar aplicaciones sin servidor fiables con Durable Functions, ya tiene conocimientos
básicos sobre qué es Durable Functions y cómo funciona. En el Capítulo 7, Desarrollar
aplicaciones sin servidor fiables con Durable Functions, implementamos la solución del
portal. Sin embargo, en este capítulo, vamos a implementar un pequeño proyecto
empleando Visual Studio 2017 (de preferencia, 15.5 o superior).

Antes de empezar a desarrollar el proyecto, tratemos de comprender el nuevo


enfoque sin servidor para implementar la solución.

[ 216 ]
Capítulo 8

Enfoque sin servidor duradero para


implementar la importación de Excel
En este diagrama se muestran todos los pasos necesarios para compilar la solución
utilizando la arquitectura sin servidor:

1. Las aplicaciones o los clientes externos cargan un archivo de Excel en el


Almacenamiento de blobs.
2. El desencadenador de blobs se desencadena después de que el archivo de
Excel se haya cargado correctamente.
3. El orquestador durable se inicia desde el desencadenador de blobs.
4. El orquestador invoca Read Excel - Activity Trigger para leer el contenido
de Excel del Almacenamiento de blobs.
5. El orquestador invoca Scale RUs - Activity Trigger para escalar
verticalmente el rendimiento de la colección de Cosmos DB para tener en
cuenta la carga.
6. El orquestador invoca Import Data - Activity Trigger para preparar la
colección para la importación masiva de datos.
7. Por último, Import Data - Activity Trigger carga los datos de la colección en
la colección de Cosmos DB empleando los enlaces de salida de Cosmos DB.

Carga de datos de los empleados en


Almacenamiento de blobs
En esta tarea, desarrollaremos una aplicación de consola que se ocupa de cargar la
hoja de Excel en el Almacenamiento de blobs.

[ 217 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

Preparación
Siga estos requisitos previos:

1. Instale Visual Studio 2017, versión 15.5 o superior.


2. Cree una cuenta de almacenamiento y un contenedor de blobs llamado
Excelimports.
3. Cree un archivo de Excel con algunos datos de empleados, como se muestra
en la siguiente captura de pantalla:

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva aplicación de consola denominada ExcelImport.Client


empleando Visual Studio, como vemos aquí:

[ 218 ]
Capítulo 8

2. Una vez creado el proyecto, ejecute los siguientes comandos en el


administrador de paquetes de 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. Agregue los siguientes espacios de nombres en el extremo 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 próximo paso es desarrollar el código en una función llamada UploadBlob
para cargar el archivo de Excel en el contenedor de blobs que creamos. Para
hacerlo más simple, el código a continuación carga el archivo de Excel desde
una ubicación codificada de forma rígida. Sin embargo, en una aplicación
típica real, el usuario final es quien carga este archivo mediante una interfaz
web. Copie el código a continuación y péguelo 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”);
}

[ 219 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

5. Ahora copie el siguiente código a la función Main. Este fragmento de código


tan solo invoca la función UploadBlob, que se encarga de cargar el blob de
manera interna:
{
UploadBlob().Wait();
}
catch (Exception ex)
{
Console.WriteLine(“An Error has occurred with the message” +
ex.Message);
}

6. El próximo paso es crear un archivo de configuración llamado appsettings.


json, que contiene la cadena de conexión de la cuenta de almacenamiento,
como figura aquí:

7. Consulte las propiedades del archivo appsettings.json y cambie Copy to


Output Directory por la opción Copy if newer, para que el programa pueda
leer las propiedades, como vemos aquí:

[ 220 ]
Capítulo 8

8. Ahora cree la aplicación y ejecútela. Si se configuraron todos los parámetros,


aparecerá lo que se muestra en la siguiente captura de pantalla:

9. Desplácese a la cuenta de almacenamiento y vaya al contenedor de blobs


llamado Excelimports, donde verá el archivo de Excel que cargó, como se
ilustra aquí:

Eso es todo. Acabamos de desarrollar una aplicación capaz de cargar el blob.

Funcionamiento...
En esta tarea, creamos una aplicación de consola que utiliza ensamblados de
almacenamiento para cargar un blob (en este caso, es solo un archivo de Excel) en
el contenedor de blobs designado. Tenga en cuenta que cada vez que se ejecuta
la aplicación, se crea un nuevo archivo en el contenedor de blobs. Para cargar los
archivos de Excel con nombres únicos, anexamos un GUID.

[ 221 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

Aún hay más...


Tome nota de las convenciones de nomenclatura que deben seguirse al crear el
contenedor de blobs:

En el momento de la redacción de este libro, este es el mensaje de error


que arroja el portal si no se respetan las reglas de nomenclatura: This
name may only contain lowercase letters, numbers, and hyphens, and
must begin with a letter or a number. Each hyphen must be preceded
and followed by a non-hyphen character. The name must also be
between 3 and 63 characters long. (Este nombre solo puede contener
letras minúsculas, números y guiones, y debe comenzar con una letra
o con un número. Cada guion debe estar precedido y seguido de un
carácter distinto del guion. Además, debe tener entre 6 y 63 caracteres.).

Creación de un desencadenador de blobs


En esta tarea, crearemos una aplicación de función con el tiempo de ejecución de
las funciones de Azure v2 y aprenderemos a crear un desencadenador de blob con
Visual Studio. También veremos cómo se activa el desencadenador de blob cuando el
archivo de Excel se carga correctamente en el contenedor de blobs.

Preparación
Siga estos requisitos previos:
1. Agregue un nuevo proyecto denominado ExcelImport.DurableFunctions
a la solución existente. Para hacerlo, elija la plantilla Azure Functions, como
se muestra aquí:

[ 222 ]
Capítulo 8

2. El siguiente paso es elegir el tiempo de ejecución de Azure Functions y el


desencadenador. Elija Azure Functions v2 (.NET Core), seleccione Blob
trigger e indique lo siguiente:

°° Storage Account (AzureWebJobsStorage): este es el nombre de la


cuenta de almacenamiento donde reside el contenedor de blobs.

°° Connection string setting: este es el nombre de clave de la cadena de


conexión que hace referencia a la cuenta de almacenamiento.
°° Path: este es el nombre del contenedor de blobs donde se cargan los
archivos de Excel.

[ 223 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

3. Al crear el proyecto, la estructura debe asemejarse a esta:

4. Vamos a agregar una cadena de conexión llamada StorageConnection


(recuerde que ya la utilizamos en el archivo de configuración de la cadena de
conexión en uno de los primeros pasos) en local.settings.json, como se
ilustra aquí:

5. Ahora abra el archivo Function1.cs y cámbiele el nombre por


ExcelImportBlobTrigger. Además, reemplace Function1 (el nombre de
la función) por ExcelImportBlobTrigger (línea 10), como se muestra más
abajo:

[ 224 ]
Capítulo 8

6. Configure ExcelImport.DurableFunctions como el proyecto


predeterminado, según figura en la siguiente captura de pantalla:

7. Cree un punto de interrupción en ExcelImportBlobTrigger y ejecute la


aplicación presionando la tecla F5. Si todo está configurado correctamente,
aparecerá esta consola:

[ 225 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

8. Ahora vamos a cargar un nuevo archivo ejecutando la aplicación


ExcelImport.Client. Inmediatamente después de cargar el archivo, se
activará el desencadenador de blobs, como se muestra en la siguiente captura
de pantalla. También se ejecutarán los puntos de interrupción junto con lo
que se ve a continuación:

Terminamos de crear el desencadenador de blobs que se ejecuta cada vez que se


agrega un nuevo blob al contenedor de blobs.

Procedimiento...
En esta tarea, creamos una nueva aplicación de función a partir del tiempo de
ejecución de las funciones de Azure v2, que se basa en el marco .NET Core y se
puede ejecutar en todas las plataformas que admitan .NET Core (por ejemplo,
sistemas operativos Windows y Linux). También creamos un desencadenador
de blobs y lo configuramos para que se ejecute cuando se agrega un nuevo blob
mediante los ajustes de la cadena de conexión. Asimismo, creamos el archivo de
configuración local.setting.json para almacenar los valores de configuración
que se emplean en el desarrollo local. Después de crear el desencadenador de blobs,
ejecutamos la aplicación ExcelImport.Client para cargar un archivo y validar que
se esté ejecutando el desencadenador de blobs.

Aún hay más...


Al ejecutar las funciones en el entorno local, se toman todas las configuraciones
del archivo local.settings.json. No obstante, al implementar las funciones en
Azure, se hará referencia a todos los elementos de las configuraciones (como la
configuración de la aplicación y la cadena de conexión) desde el campo Application
Settings de su aplicación de función. Asegúrese de crear todos los elementos de
configuración en la aplicación de función después de implementar las funciones.

[ 226 ]
Capítulo 8

Creación del orquestador durable


y desencadenarlo para cada
importación de Excel
Esta tarea es una de las más importantes e interesantes. Aprenderemos a crear el
orquestador durable encargado de administrar todas las funciones de actividad
que creemos para las diferentes tareas individuales requeridas para completar el
proyecto ExcelImport.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva función haciendo clic derecho en ExcelImport.


DurableFunctions, haga clic en Add y elija New Azure Function, como se
muestra en la siguiente captura de pantalla:

2. En la ventana emergente Add new Item, elija Azure Function, especifique el


nombre ExcelImport_Orchestrator y haga clic en Add, como se ilustra aquí:

[ 227 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

3. En la ventana emergente New Azure Function, seleccione la plantilla


Durable Function Orchestration y haga clic en el botón OK, con lo cual se
creará lo siguiente:

° HttpStart: esta es la función de inicio de Durable Function


(un desencadenador HTTP) que trabaja como un cliente que
puede invocar al orquestador durable. Sin embargo, en nuestro
proyecto, no emplearemos este desencadenador HTTP, sino que
utilizaremos la lógica incluida en él en el desencadenador de blobs
ExcelImportBlobTrigger para invocar al orquestador durable.

° RunOrchestrator: este es el orquestador durable real capaz de


invocar y administrar las funciones de actividad.
° SayHello: una función de actividad sencilla. Vamos a crear algunas
funciones de actividad. Vamos a avanzar y eliminar este método:

[ 228 ]
Capítulo 8

4. En el desencadenador de blobs ExcelImportBlobTrigger, incorporemos los


siguientes cambios en el código para invocar al orquestador:

°° Extienda la función para que sea asincrónica.


°° Agregue los enlaces de salida del cliente de orquestación.
°° Llame a StartNewAsync empleando el cliente
DurableOrchestrationClient.

5. El código en la función ExcelImportBlobTrigger debe asemejarse al


siguiente después de hacer estos 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. Cree un punto de interrupción en la función de orquestador ExcelImport_


Orchestrator y presione F5 para ejecutar la aplicación.

[ 229 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

7. Cargaremos un nuevo archivo (mientras ExcelImport.DurableFunctions


se está ejecutando). Para ello, ejecute la función ExcelImport.Client.
(También puede cargar directamente el archivo de Excel desde el portal de
Azure). Una vez cargado el archivo, espere unos instantes para que se ejecute
el punto de interrupción en la función ExcelImport_Orchestrator, como se
muestra aquí:

Aprendimos a invocar la función de orquestación durable desde el desencadenador


de blobs.

Funcionamiento...
Al comienzo de esta tarea, creamos la función de orquestación y luego modificamos
el desencadenador de blobs ExcelImportBlobTrigger agregando los enlaces de
salida OrchestratonClient para invocar la función de orquestador durable.

Al crear una nueva función de orquestación, también se crean algunas funciones de


actividad. En las próximas tareas, las eliminaremos y crearemos nuevas funciones de
actividad según nuestros requisitos.

Aún hay más...


En esta tarea, empleamos DurableOrchestrationClient, que comprende cómo
iniciar y terminar las orquestaciones durables.

[ 230 ]
Capítulo 8

Estas son algunas de las operaciones importantes que se admiten:

• Iniciar una instancia utilizando el método StartNewAsync.


• Terminar una instancia utilizando el método TerminateAsync.
• Consultar el estado de la instancia en ejecución actual utilizando el método
GetStatusAsync.
• También puede generar un evento en la instancia para actualizarlo respecto
a los eventos externos utilizando el método RaiseEventAsync.

Puede obtener más información al respecto en https://docs.


microsoft.com/en-us/azure/azure-functions/durable-
functions-instance-management#sending-events-to-
instances.

Lectura de datos de Excel utilizando


funciones de actividad
En esta tarea, vamos a recuperar todos los datos de hojas de Excel específicas
escribiendo una función de actividad.
Ahora realicemos algunos cambios en el código de la función de orquestación. Para
ello, escriba una nueva función de actividad que pueda leer datos de una hoja de
Excel cargada en el contenedor de blobs.

Preparación
En esta tarea, crearemos el desencadenador de actividad denominado función
ReadExcel_AT que lee los datos desde el blob almacenado en la cuenta de
almacenamiento. Este desencadenador de actividad realiza los siguientes trabajos:

Se conecta al blob utilizando una función, ReadBlob, de una clase llamada


StorageManager.
1. Lee los datos de Excel empleando un componente denominado EPPlus.
Puede obtener más información sobre este tema en https://github.com/
JanKallman/EPPlus.
2. Devuelve los datos del archivo de Excel como una colección de objetos
de empleados.
A continuación, instale los siguientes paquetes de NuGet en el proyecto
ExcelImport.DurableFunctions:
Install-Package WindowsAzure.Storage
Install-Package EPPlus

[ 231 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

Procedimiento...
Si piensa en Durable Functions como un flujo de trabajo, la función de
desencadenador de actividad bien se podría tratar como un paso de flujo de trabajo
que obtiene algún tipo de entrada opcional, realiza alguna funcionalidad y devuelve
una salida opcional. Este es uno de los conceptos centrales de Azure Durable
Functions.

Puede 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 compilar la función de desencadenador de actividad,


compilaremos las funciones de dependencia.

Leer datos del Almacenamiento de blobs


Lleve a cabo los pasos siguientes:

1. Cree una clase llamada StorageManager y péguela en el código


a continuación. Este código se conecta con la cuenta de almacenamiento
especificada, lee los datos de los blobs y devuelve el objeto Stream a la
función de solicitante:
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();
}
}

[ 232 ]
Capítulo 8

2. Pegue estas referencias de espacios 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, agregue una cadena de conexión (si aún no lo hizo) para la
cuenta de almacenamiento al archivo local.settings.json, como se
muestra aquí:

Leer los datos de Excel de la secuencia


Lleve a cabo los pasos siguientes:
1. Cree una clase llamada EPPLusExcelManager y pegue el siguiente código.
Esta clase posee un método denominado ReadExcelData, que emplea una
biblioteca llamada EPPlus para leer los datos del archivo de Excel (extensión
.xlsx). Se encarga de leer cada fila, crear el objeto Employee para cada una
de ellas y devolver una colección de empleados. Crearemos 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++)
{

[ 233 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

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. Ahora crearemos otra clase llamada Employee y copiaremos el código


a continuación:
public class Employee
{
public string EmpId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
}

Si compila la aplicación ahora, no debería ver ningún error. Acabamos de desarrollar


las dependencias para nuestra primera función de desencadenador de actividad.
Ahora comencemos a compilar el desencadenador de actividad real.

Crear la función de actividad


Lleve a cabo los pasos siguientes:

1. Cree una nueva función de actividad llamada ReadExcel_AT que se


conecte con el blob utilizando la clase StorageManager que desarrollamos
en la sección anterior y que luego lea los datos a través de la clase
EPPLusExcelManager. Copie el código a continuación en la clase
ExcelImport_Orchestrator:
[FunctionName(“ReadExcel_AT”)]
public static async Task<List<Employee>> ReadExcel_AT(
[ActivityTrigger] string name,
ILogger log)
{

[ 234 ]
Capítulo 8

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. Agregue System.IO a la lista de espacios de nombres, si todavía no está allí,


y compile la aplicación.
3. Ahora invoquemos esta función de actividad desde el orquestador. Diríjase
a la función de orquestador ExcelImport_Orchestrator y reemplácela
por el siguiente código. Para invocar la función de actividad, la función
de orquestación pasa el nombre del Excel cargado para que la función de
actividad pueda leer 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;
}

[ 235 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

4. Ejecute la aplicación y luego cargue un archivo de Excel. Si todo está


configurado correctamente, aparecerá lo que se muestra más abajo en la
función de desencadenador de actividad RealExcel_AT, donde podrá ver la
cantidad de registros de empleados que se están leyendo desde la hoja
de Excel:

Aún hay más...


La función de orquestador recibe la entrada a través del método GetInput()
de la clase DurableOrchestratorContext. El desencadenador de blobs pasa
esta entrada utilizando el método de la función StartNewAsync de la clase
DurableOrchestrationClient.

[ 236 ]
Capítulo 8

Escalado automático del rendimiento de


Cosmos DB
En la tarea anterior, leímos los datos de Excel y los colocamos 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 hacerlo, es importante considerar que, en escenarios reales,
la cantidad de registros que solemos importar puede llegar a ser enorme, por lo que
podría enfrentar problemas de rendimiento si la colección de Cosmos DB no tiene
capacidad suficiente.

El rendimiento de una colección de Cosmos DB se calcula según la


cantidad de unidades de solicitud (RU) asignadas a la colección.
Puede 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 costos, se recomienda trabajar con una capacidad
mínima para cada servicio y aumentarla cuando sea necesario. La API de Cosmos
DB nos permite controlar la cantidad de RU en función de nuestras necesidades.
Debido a que 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 nivel mínimo.

Preparación
Siga estos requisitos previos:

1. Para crear una cuenta de Cosmos DB, siga las instrucciones mencionadas
en el artículo que se encuentra en https://docs.microsoft.com/en-us/
azure/cosmos-db/create-sql-api-dotnet.

[ 237 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

2. Cree una base de datos de Cosmos y una colección con almacenamiento fijo
y configure las unidades de solicitud en 400 por segundo, como se muestra
en la siguiente captura de pantalla:

Para fines de simplicidad, elegí Fixed (10 GB) en el campo Storage


capacity. No obstante, en las cargas de producción y según los modelos de
datos, es posible que tenga que seleccionar Unlimited como capacidad de
almacenamiento.
3. Ejecute el siguiente comando en el administrador de paquetes de NuGet para
instalar las dependencias de Cosmos DB:
Install-Package Microsoft.Azure.WebJobs.Extensions.CosmosDB

[ 238 ]
Capítulo 8

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree un nuevo desencadenador de actividad denominado ScaleRU_AT en el


archivo ExcelImport_Orchestrator.cs. La función debe tener un aspecto
parecido a este y aceptar la cantidad de RU a las cuales escalar, junto con el
enlace de Cosmos DB utilizando el cual reemplazamos 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ñada estos espacios de nombres al archivo ExcelImport_Orchestrator.


cs:

using System.Linq;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;

[ 239 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

3. Cree una nueva cadena de conexión para Cosmos DB, como se muestra en
esta captura de pantalla. Puede copiar la conexión desde la hoja Keys de la
cuenta de Cosmos DB:

4. En la función ExcelImport_Orchestrator, agregue la siguiente línea para


invocar ScaleRU_AT. En este ejemplo, estoy procesando 500 como el valor de
RU. Según sus necesidades, puede elegir un valor diferente:
await context.CallActivityAsync<string>(“ScaleRU_AT”, 500);

5. A continuación, cargue un archivo de Excel para desencadenar la


orquestación, que invoca el desencadenador de actividad nuevo de manera
interna, ScaleRU_AT. Si todo funciona de manera correcta, la nueva
capacidad de la colección de Cosmos DB debería ser 500. Navegue hasta la
pestaña Data Explorer de Cosmos DB y diríjase a la sección Scale & Settings,
donde puede ver 500 como el nuevo rendimiento de la colección, tal como se
muestra aquí:

[ 240 ]
Capítulo 8

Aún hay más...


La capacidad de la colección de Cosmos DB está representada como un recurso
llamado oferta. En esta tarea, recuperamos la oferta existente y la reemplazamos
por una nueva. Puede obtener más información sobre este tema en
https://docs.microsoft.com/en-us/rest/api/cosmos-db/offers.

Inserción masiva de datos en Cosmos DB


Ahora que ya escalamos la colección, es momento de insertar los datos en la
colección de Cosmos DB. En esta tarea, aprenderemos una de las formas más
sencillas de insertar datos en Cosmos DB para hacer que la tarea sea simple y directa.

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree un nuevo desencadenador de actividad llamado ImportData_AT,


que toma la colección de los empleados como entrada y guarda los datos
en la colección. Pegue 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. Agregue la línea a continuación a la función de orquestación que invoca el


desencadenador de actividad ImportData_AT:
await context.CallActivityAsync<string>(“ImportData_AT”,
employees);

[ 241 ]
Importación masiva de datos utilizando Azure Durable Functions y Cosmos DB

Vamos a ejecutar la aplicación y cargar un archivo de Excel para probar


la funcionalidad. Si todo salió bien, verá todos los registros creados en la
colección de Cosmos DB, como se muestra aquí:

Aún hay más...


El equipo de Cosmos DB ha publicado una biblioteca denominada ejecutor masivo
de Cosmos DB. Puede obtener más información sobre este tema en https://docs.
microsoft.com/en-us/azure/cosmos-db/bulk-executor-overview.

Para simplificar esta tarea, codifiqué de forma rígida el nombre de la colección


y de la base de datos. Tendrá que configurarlos en el archivo de configuración
de la aplicación.

[ 242 ]
Implementar procedimientos
recomendados para
Azure Functions
En este capítulo, aprenderá algunos de los procedimientos recomendados que se
pueden seguir al trabajar con Azure Functions, como los siguientes:

• Incorporación de varios mensajes a una cola utilizando la función


IAsyncCollector.
• Implementación de aplicaciones defensivas con Azure Functions
y desencadenadores de cola.
• Control del ingreso masivo utilizando Event Hubs para IoT y otros
escenarios similares.
• Prevención de arranques en frío activando la aplicación a intervalos constantes.
• Habilitación de la autorización para aplicaciones de función.
• Control de acceso a funciones de Azure utilizando claves de función.
• Protección de las funciones de Azure utilizando Azure Active Directory.
• Configuración de la limitación de Azure Functions utilizando
API Management.
• Acceso seguro a SQL Database desde Azure Functions utilizando
Managed Service Identity.
• Código compartido entre las funciones de Azure utilizando bibliotecas
de clases.
• Uso de clases fuertemente tipadas en Azure Functions.

[ 243 ]
Implementar procedimientos recomendados para Azure Functions

Incorporación de varios mensajes a una


cola utilizando la función IAsyncCollector
En el primer capítulo, aprendió a crear un mensaje de cola para cada solicitud
procedente de la solicitud de HTTP. Ahora supongamos que cada usuario registra
sus dispositivos utilizando 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 recibe. Es decir,
debe existir un mecanismo para crear varios mensajes de cola a la vez y de forma
asincrónica. Aprenderá a crear varios mensajes de cola utilizando la interfaz
IAsyncCollector.

A continuación, se muestra un diagrama que representa el flujo de datos


de diferentes aplicaciones cliente a la API web de back-end:

En esta tarea, simularemos las solicitudes utilizando Postman, que enviará la


solicitud a la API web de back-end (HTTPTrigger), la cual puede crear todos
los mensajes de cola de una sola vez.

Preparación
Estos son los pasos necesarios:

1. Cree una cuenta de almacenamiento utilizando el portal de Azure, si aún no


ha hecho.
2. Instale el explorador de Microsoft Storage desde
http://storageexplorer.com/ si todavía no lo instaló.
[ 244 ]
Capítulo 9

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree un nuevo desencadenador HTTP llamado BulkDeviceRegistrations.


Para ello, configure Authorization Level en Anonymous.
2. Reemplace el código predeterminado por el siguiente código y haga clic
en el botón Save para guardar los cambios. Este código espera una matriz
JSON como parámetro de entrada con un atributo denominado Devices. Si la
encuentra, se iterará a través de los elementos de matriz y los mostrará en los
registros. Más adelante, modificaremos el programa para insertar de forma
masiva los elementos de 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 próximo paso es crear un enlace de salida para Azure Queue Storage.


Haga clic en el botón Save, navegue hasta la pestaña Integrate y agregue
un nuevo enlace de salida para Azure Queue Storage. Luego haga clic en
el botón Select y proporcione el nombre de la cola y otros parámetros.

[ 245 ]
Implementar procedimientos recomendados para Azure Functions

4. Haga clic en el botón Save y diríjase al editor de código de la función de


Azure. Agregue 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.
Realice los cambios resaltados en el editor de código y haga clic en el botón
Save 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 Test del portal con este JSON
de solicitud de entrada:
{
"devices":
[
{
"type": "laptop",
"brand":"lenovo",
"model":"T440"
},
{
"type": "mobile",
"brand":"Mi",
"model":"Red Mi 4"
}
]
}

6. Haga clic en el botón Run para probar la funcionalidad. Ahora abra el


explorador de Azure Storage y desplácese hasta la cola denominada
devicequeue. Como se muestra aquí, aparecen dos registros:

[ 246 ]
Capítulo 9

Funcionamiento...
Creamos una nueva función HTTP que posee un parámetro del tipo
IAsyncCollector<string>, que sirve para almacenar varios mensajes en un
servicio de cola de una sola vez y de forma asincrónica. Este enfoque, que consiste en
almacenar varios elementos de forma asincrónica, reducirá la carga en las instancias.

Por último, probamos la invocación del desencadenador HTTP desde el portal


de Azure y también vimos que se agregaron los mensajes de cola utilizando el
explorador de Azure Storage.

Aún hay más...


También puede utilizar la interfaz ICollector en lugar de IAsyncCollector si
desea almacenar varios mensajes de forma asincrónica.

Tenga en cuenta que quizá tenga que instalar extensiones de


Azure Storage para agregar enlaces de salida, si todavía no lo
hizo. En el tiempo de ejecución de las funciones de Azure v2, es
obligatorio agregar extensiones para cada uno de los servicios
(en este caso, el almacenamiento).

Implementación de aplicaciones
defensivas con Azure Functions
y desencadenadores de cola
Para muchas aplicaciones, incluso después de realizar varias pruebas de diferentes
entornos, es posible que aún existan motivos imprevistos por los que la aplicación
puede fallar. Los desarrolladores y arquitectos no pueden predecir todas las
entradas imprevistas durante la vida útil de la aplicación que empleen los usuarios
empresariales o los usuarios finales generales. Por lo tanto, es una buena forma de
asegurarse de que la aplicación le avise si hay errores o problemas inesperados con
las aplicaciones.
[ 247 ]
Implementar procedimientos recomendados para Azure Functions

En esta tarea, aprenderá cómo Azure Functions nos ayuda a controlar este tipo
de problemas con un código mínimo.

Preparación
Estos son los pasos necesarios:
1. Cree una cuenta de almacenamiento utilizando el portal de Azure, si aún
no ha hecho.
2. Instale el explorador de Azure Storage desde http://storageexplorer.com/
si aún no lo hizo.

Procedimiento...
En esta tarea, haremos lo siguiente:
• Desarrollar una aplicación de consola mediante C#, que se conecta con la
cuenta de almacenamiento y crea mensajes de la cola en la cola denominada
myqueuemessages.
• Crear un desencadenador de cola para la función de Azure llamado
ProcessData que se active cada vez que se agregue un mensaje nuevo
a la cola denominada myqueuemessages.

Aplicar la consola, CreateQueueMessage,


mediante C#
Lleve a cabo los pasos siguientes:
1. Cree una nueva aplicación de consola empleando el lenguaje C#
de .NET Core y una clave de configuración de aplicación llamada
StorageConnectionString con la cadena de conexión de su cuenta de
almacenamiento. Puede obtener la cadena de conexión de la hoja Access
Keys de la cuenta de almacenamiento, como se muestra a continuación:

2. Instale los paquetes de NuGet Configuration y Queue Storage empleando


estos comandos:
Install-Package Microsoft.Azure.Storage.Queue
Install-Package System.Configuration.ConfigurationManager

3. Agregue los siguientes espacios de nombres:


using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
using System.Configuration;
[ 248 ]
Capítulo 9

4. Agregue a su aplicación de consola la función a continuación y solicítela


desde el método Main. La función CreateQueueMessages genera 100
mensajes con el índice como contenido de cada uno de ellos:
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 función de Azure, desencadenador


de cola
Lleve a cabo los pasos siguientes:
1. Cree una nueva función de Azure llamada ProcessData empleando el
desencadenador de cola y configure la cola myqueuemessages. Así debe
verse la pestaña Integrate después de crear la función:

[ 249 ]
Implementar procedimientos recomendados para Azure Functions

2. Reemplace el código predeterminado por el 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


(que es simplemente un índice numérico) para los primeros 50 mensajes y luego
arroja una excepción para aquellos mensajes cuyo contenido es superior a 50.

Ejecutar pruebas utilizando la aplicación de consola


Lleve a cabo los pasos siguientes:

1. Ejecutaremos la aplicación de consola. Para ello, presione Ctrl + F5, vaya al


explorador de Azure Storage y consulte el contenido de cola.
2. En tan solo unos instantes, empezará a ver mensajes en la cola
myqueuemessages. Actualmente, tanto el portal de Azure como el explorador
de Storage muestran los primeros 32 mensajes. Debe utilizar Storage SDK
mediante C# para ver todos los mensajes de la cola.

No se sorprenda si ve que los mensajes en myqueuemessage


desaparecen. Recuerde que los mensajes que se leen correctamente se
eliminan de la cola al instante.

3. Como se muestra aquí, también aparecerá una nueva cola denominada


myqueuemessages-poison (<OriginalQueuename>-Poison) que contiene
el resto de los 50 mensajes de cola. El tiempo de ejecución de la función
de Azure se encargará, de forma automática, de crear una nueva cola
y de agregar los mensajes que Azure Functions no lee correctamente:

[ 250 ]
Capítulo 9

Funcionamiento...
Creamos una aplicación de consola que genera mensajes en Azure Queue Storage
y también desarrollamos un desencadenador de cola capaz de leer los mensajes de la
cola. Como parte de la simulación de un error inesperado, aparece un error si el valor
del contenido del mensaje de cola es mayor a 50.

Azure Functions se encargará de crear una nueva cola con el nombre


<OriginalQueueName>-Poison e insertará todos los mensajes sin procesar allí. 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 tiempo de ejecución de la función de Azure se encargará de eliminar el mensaje de


cola después de que la ejecución de la función de Azure se complete correctamente.
Si hay algún problema en la ejecución de la función de Azure, crea automáticamente
una nueva cola de daños y agrega los mensajes procesados a la nueva cola.

Aún hay más...


Antes de insertar un mensaje de cola en la cola de daños, el tiempo de ejecución de la
función de Azure intenta seleccionar el mensaje y procesarlo cinco veces. Para saber
cómo funciona este proceso, agregue el nuevo parámetro dequecount del tipo int al
método Run y registre su valor.

[ 251 ]
Implementar procedimientos recomendados para Azure Functions

Control del ingreso masivo utilizando


Event Hubs para IoT y otros escenarios
similares
En muchos escenarios, es posible que tenga que controlar grandes cantidades
de datos entrantes, que pueden venir de sensores y datos de telemetría. Esta tarea
podría ser tan simple como los datos enviados desde los dispositivos de Fitbit.
En estas situaciones, necesitamos tener una solución fiable capaz de manejar
cantidades masivas de datos. Azure ofrece una solución para esto llamada Azure
Event Hubs. En esta tarea, aprenderá a integrar Event Hubs y Azure Functions.

Preparación
Lleve a cabo los pasos siguientes:
1. Cree el espacio de nombres Event Hubs. Para hacerlo, desplácese hasta
Internet of Things y elija Event Hubs.
2. Una vez que el espacio de nombre Event Hubs esté creado, navegue hasta
la pestaña Overview y haga clic en el ícono Event Hub para crear un nuevo
parámetro Event Hub.
3. De forma predeterminada, el sistema crea un grupo de consumidores en
Consumer Group denominado $Default, que utilizaremos en esta tarea.

Procedimiento...
En esta tarea, haremos lo siguiente:
• Crear un desencadenador de Event Hub para una función de Azure.
• Desarrollar una aplicación de consola que simule datos de la Internet de las
Cosas (IoT).

Crear un desencadenador de Event Hub para una


función de Azure
Lleve a cabo los pasos siguientes:
1. Cree una nueva función de Azure eligiendo Event Hub Trigger en la lista de
plantillas.
2. Después de seleccionar la plantilla, es posible que tenga que instalar las
extensiones. A continuación, deberá proporcionar el nombre del centro de
eventos, capturemessage. Si aún no tiene ninguna conexión configurada,
haga clic en el botón New.
3. Al hacer clic en el botón New, se abrirá la ventana emergente Connection,
donde podrá elegir su centro de eventos y demás detalles. Elija los detalles
necesarios y haga clic en el botón Select, como se muestra aquí:
[ 252 ]
Capítulo 9

4. El paso anterior rellenará el menú desplegable Event Hub Connection. Por


último, haga clic en Create para crear la función.

Desarrollar una aplicación de consola que


simule datos de IoT
Lleve a cabo los pasos siguientes:

1. Cree una nueva aplicación de consola para enviar eventos al centro de


eventos. La llamé EventHubApp.
2. Ejecute los siguientes comandos en el administrador de paquetes de NuGet
para instalar las bibliotecas correspondientes e interactuar con Azure Event
Hubs:
Install-Package Microsoft.Azure.EventHubs
Install-Package Newtonsoft.Json

3. Agregue estos espacios de nombres y una referencia a System.


Configuration.dll:
using Microsoft.Azure.EventHubs;
using System.Configuration;

4. Agregue la cadena de conexión a App.config, que sirve para conectarse


con el centro de eventos. Este es el código para App.config. Para obtener la
cadena de conexión, haga clic en el enlace ConnectionStrings en la pestaña
Overview 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"
[ 253 ]
Implementar procedimientos recomendados para Azure Functions

value="Endpoint=sb://<event hub namespace


here>.servicebus.windows.net/;Entitypath=<Event
Hubname>;
SharedAccessKeyName= RootManageSharedAccessKey;
SharedAccessKey=<Key here>"/>
</appSettings>
</configuration>

5. Cree un nuevo archivo de clase de C# y coloque el código siguiente allí:


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 la función main, ubique el código a continuación que invoca el método


para enviar el mensaje:
namespace EventHubApp
{

[ 254 ]
Capítulo 9

class Program
{
static void Main(string[] args)
{
EventHubHelper.GenerateEventHubMessages().Wait();
}
}
}

7. Ahora pulse Ctrl + F5 para ejecutar la aplicación. Aparecerá una pantalla


similar a esta:

8. Cuando la consola imprime los números, puede desplazarse a la función


de Azure para comprobar que el centro de eventos se desencadena
automáticamente y registra los números que se envían a él.

[ 255 ]
Implementar procedimientos recomendados para Azure Functions

Prevención de arranques en frío activando


la aplicación a intervalos constantes
Hasta ahora, sabe que puede crear funciones de Azure en los siguientes dos planes
de hospedaje:

• Plan de App Service


• Plan de consumo

Obtendrá todas las ventajas de la arquitectura sin servidor solo cuando cree
la aplicación de función utilizando el plan de consumo. Sin embargo, una de
las preocupaciones que los desarrolladores informan sobre el uso del plan de
consumo es algo llamado "arranque en frío", que se refiere a la puesta en marcha
de una función de Azure para atender las solicitudes cuando no ha habido
solicitudes durante bastante tiempo. Puede obtener más información sobre este
tema en https://blogs.msdn.microsoft.com/appserviceteam/2018/02/07/
understanding-serverless-cold-start/.

En esta tarea, aprenderemos una técnica para mantener la instancia siempre activa
de modo que pueda servir a todas las solicitudes correctamente.

El plan de App Service es un plan de hospedaje dedicado


donde las instancias están reservadas para usted y siempre
pueden estar activas, incluso si no hay solicitudes por un
tiempo.

Preparación
Con el fin de completar esta tarea, necesitamos tener una aplicación de función con
lo siguiente:

• Un desencadenador de HTTP llamado HttpALive.


• Un desencadenador de temporizador llamado KeepFunctionAppWarm que
se ejecute cada 5 minutos y realice una solicitud de HTTP al desencadenador
HTTP HttpALive.

Si ya comprendió con claridad qué es un arranque en frío, sabe que no tiene que
preocuparse si su aplicación tiene tráfico habitualmente durante el día. Por lo
tanto, si podemos asegurarnos de que la aplicación tenga tráfico durante todo el
día, la instancia de la función de Azure no se desaprovisionará y no habrá ninguna
inquietud sobre el plan de consumo.

[ 256 ]
Capítulo 9

Procedimiento...
En esta tarea, crearemos un desencadenador de temporizador que simule el tráfico
al desencadenador HTTP, haciendo que la aplicación de función esté activa todo el
tiempo y las instancias sin servidor estén siempre en el estado aprovisionado.

Crear un desencadenador HTTP


Cree un nuevo desencadenador HTTP y reemplace el siguiente código que
únicamente 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


Lleve a cabo los pasos siguientes:

1. Haga clic en el ícono +, busque el temporizador y haga clic en el botón Timer


trigger.
2. En la ventana emergente New Function, especifique los detalles. En el campo
Schedule figura una expresión CRON que garantiza que el desencadenador
de temporizador se active automáticamente cada 5 minutos:

[ 257 ]
Implementar procedimientos recomendados para Azure Functions

3. Pegue el siguiente código en el editor de código y guarde los cambios.


Este código simula el tráfico realizando solicitudes de HTTP mediante
programación. Asegúrese de reemplazar el campo <<FunctionAppName>>
por el nombre real de su aplicación de función:
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");
}
}

Aún hay más...


Si explora un poco Azure Functions, observará que los tiempos de arranque en
frío para las funciones de Azure que emplean el lenguaje C# son de apenas unos
segundos. Sin embargo, si está trabajando con funciones de Azure configuradas con el
lenguaje JavaScript (como Node. js), el tiempo de arranque en frío será mayor, ya que
el tiempo de ejecución debe descargar todos los paquetes npm que son dependencias
de la aplicación. En esos casos, la característica denominada Run-From-Package
resulta muy práctica. Aprenderemos a implementarla en el próximo capítulo.

Consulte también
Consulte la tarea Implementación de Azure Functions utilizando Run From Package del
Capítulo 10, Configurar aplicaciones sin servidor en el entorno de producción.

Habilitación de la autorización para


aplicaciones de función
Si muchas aplicaciones cliente están utilizando su API web (desencadenador HTTP)
y desea brindar acceso solo a las aplicaciones previstas y autorizadas, deberá
implementar la autorización para restringir el acceso a la función de Azure.

Preparación
Supongo que ya sabe crear una función de desencadenador HTTP. Descargue la
herramienta Postman desde https://www.getpostman.com/. La herramienta
Postman se utiliza para enviar solicitudes de HTTP. También se puede utilizar
cualquier herramienta o aplicación que envíe encabezados y solicitudes de HTTP.
[ 258 ]
Capítulo 9

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva función de desencadenador HTTP (o abra una función


HTTP existente). Cuando cree la función, asegúrese de seleccionar Function
como opción del menú desplegable en el nivel Authorization.

Si desea utilizar una función de desencadenador HTTP actual


que creó en las tareas anteriores, haga clic en la pestaña
Integrate, cambie el nivel Authorization por Function y haga
clic en el botón Save para guardar los cambios.

2. En la pestaña Code Editor, obtenga la URL de la función haciendo clic en el


enlace Get Function URL ubicado en el extremo derecho del editor de código
en el archivo run.csx.
3. Diríjase a Postman y pegue la dirección URL de la función:

4. Observe que la dirección URL tiene las siguientes cadenas de consulta:


°° code: esta es la cadena de consulta predeterminada esperada por
el tiempo de ejecución de la función y que valida los derechos
de acceso de la función. La funcionalidad de validación se activa
automáticamente sin que el desarrollador tenga que escribir el
código. Para contemplar todo esto, basta con configurar el nivel
Authorization como Function.
°° name: esta es la cadena de consulta que requiere la función de
desencadenador HTTP.

5. Vamos a quitar la cadena de consulta de código de la dirección URL


en Postman e intentar realizar una solicitud. Aparecerá el error 401
Unauthorized.

[ 259 ]
Implementar procedimientos recomendados para Azure Functions

Funcionamiento...
Cuando realiza una solicitud a través de Postman o de cualquier otra herramienta
o aplicación capaz de enviar solicitudes de HTTP, la aplicación web de Azure App
Service subyacente recibe la solicitud (tenga en cuenta que las funciones de Azure
se generan sobre App Services) y, primero, comprueba la presencia del código de
nombre del encabezado en la colección de cadenas de consulta o en el cuerpo de la
solicitud. Si lo encuentra, la herramienta 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
tiempo de ejecución la procese. De lo contrario, se produce un error con el mensaje
401 Unauthorized.

Aún hay más...


Tenga en cuenta que la clave de seguridad (expresada en el parámetro de la
cadena de consulta llamado code) en el ejemplo anterior se utiliza solo para
fines de demostración. En los entornos de producción, en lugar de pasar la clave
como parámetro de la cadena de consulta (el parámetro code), tiene que agregar
x-functions-key como encabezado HTTP, como se observa en esta captura
de pantalla:

Control de acceso a funciones de Azure


utilizando claves de función
Ya aprendió a habilitar la autorización de un desencadenador HTTP individual
configurando el campo Anonymous Level con la función value en la pestaña
Integrate de la función trigger HTTP. Esto funciona bien si solo tiene una función
de Azure como un API web de back-end para una de sus aplicaciones y no desea
restringir el acceso al público.

[ 260 ]
Capítulo 9

Sin embargo, en las aplicaciones empresariales, terminará desarrollando muchas


funciones de Azure en varias aplicaciones de función. En esos casos, debe tener
un acceso granular específico a su función de Azure para las aplicaciones propias
o para otras aplicaciones de terceros que integran las API de su propiedad en sus
aplicaciones.

En esta tarea, aprenderá a trabajar con claves de función dentro de Azure Functions.

Procedimiento...
Azure es compatible con las siguientes claves, que se pueden utilizar para controlar
el acceso a las funciones de Azure:

• Claves de función: sirven para conceder 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: sirven 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 está desarrollando una API con las funciones de Azure que pueden ser utilizadas
por varias aplicaciones, se recomienda tener una clave de función diferente para cada
aplicación cliente que vaya a utilizarlas.

Vaya a la pestaña Manage de Azure Functions para ver y administrar todas las
claves relacionadas con la función.

De forma predeterminada, el sistema genera una clave con el nombre Default. Si


desea generar una nueva clave, haga clic en el botón Add new function.

Según la instrucción anterior, creé las claves para las siguientes aplicaciones:

• WebApplication: el nombre de clave WebApplication está configurado para


utilizarse en el sitio web donde se emplea la función de Azure.
• MobileApplication: el nombre de clave MobileApplication está
configurado para utilizarse en la aplicación móvil donde se emplea la función
de Azure.

De la misma manera, puede crear diferentes claves para cualquier otra aplicación
(por ejemplo, una aplicación de IoT) en función de sus requisitos.

[ 261 ]
Implementar procedimientos recomendados para Azure Functions

La idea de tener diferentes claves para la misma función es controlar los permisos
de acceso para las distintas aplicaciones que utilizan las funciones. Por ejemplo, si
desea revocar los permisos para una aplicación y no para todas, basta con eliminar
(o revocar) esa clave. De ese modo, no afectará a las demás aplicaciones que utilizan
la misma función.

Sin embargo, las claves de función presentan una desventaja. Si está desarrollando
una aplicación donde necesita tener varias funciones y cada función está siendo
utilizada por muchas aplicaciones, entonces terminará teniendo muchas claves.
Administrar estas claves y documentarlas sería una pesadilla. En ese caso,
puede optar por claves de host, como las que se explican a continuación.

Configurar una clave de host para todas las


funciones en una única aplicación de función
Se recomienda tener diferentes claves para diferentes funciones cuando hay pocas
aplicaciones que utilizan muchas funciones. Sin embargo, las cosas se complican
si tiene muchas funciones y muchas aplicaciones cliente que aprovechan sus API.
Administrar las claves de función en estas grandes aplicaciones empresariales
con enormes bases de clientes sería un problema. Para simplificar las cosas, puede
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. Puede configurar la autorización para una aplicación
de función utilizando claves de host.

Aquí se detallan dos tipos diferentes de claves de host disponibles:

• Claves de host normales


• Clave maestra

Cree dos aplicaciones de desencadenador HTTP, como se muestra en esta captura


de pantalla:

[ 262 ]
Capítulo 9

Navegue hasta la pestaña Manage de ambas aplicaciones, como vemos aquí.


Observe que tanto la clave maestra como las claves de host son las mismas en
ambas 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 puede crear varias
claves de host si diversas aplicaciones utilizan sus aplicaciones
de función. Puede emplear diferentes claves para controlar el acceso
de cada aplicación individual a cada una de las aplicaciones de función.
Asimismo, puede crear varias claves de host siguiendo los mismos
pasos que para crear las claves de función normales.

[ 263 ]
Implementar procedimientos recomendados para Azure Functions

Aún hay más...


Si considera que la clave está en peligro, puede regenerarla en cualquier momento
haciendo clic en el botón Renew. Tenga en cuenta que cuando renueva una clave,
todas las aplicaciones que acceden a la función dejan de funcionar y muestran el
error de código de estado 401 Unauthorized.

Puede eliminar o revocar la clave si ya no se utiliza en ninguna de las aplicaciones.

Aquí se incluye una tabla con más información sobre las claves:

Tipo de ¿Cuándo ¿Es ¿Renovable? Comentarios


clave debo revocable
utilizarla? (se puede
borrar)?
Clave Cuando No Sí Puede utilizar una
maestra el nivel clave maestra para
Authorization cualquier función dentro
es Admin de la aplicación de
función, más allá del
nivel de autorización
configurado.
Clave de Cuando Sí Sí Puede utilizar la clave
host el nivel de host para todas las
Authorization funciones dentro de la
es Function aplicación de función.
Clave de Cuando Sí Sí Puede utilizar la clave
función el nivel de función solo para una
Authorization función determinada.
es Function

Microsoft no recomienda compartir la clave maestra, ya que


también la utilizan las API en tiempo de ejecución. Tenga especial
precaución con las claves maestras.

Protección de las funciones de Azure


utilizando Azure Active Directory
En la tarea anterior, aprendimos a habilitar la seguridad según las aplicaciones
cliente que acceden a las funciones de Azure. No obstante, si necesita autenticar a los
usuarios finales que acceden a las funciones en Azure Active Directory (AD), Azure
Functions ofrece una forma sencilla de hacerlo denominada EasyAuth.
[ 264 ]
Capítulo 9

Gracias a Azure App Service, desde el que se hereda la característica EasyAuth,


podemos hacer lo que necesitamos hacer sin escribir una sola línea de código.

Preparación
En esta tarea, para simplificar las cosas, utilizaremos el AD predeterminado que
se crea al crear una cuenta de Azure. Sin embargo, en los entornos de producción
reales, es posible que ya tenga un AD que necesita integrarse. Recomiendo consultar
este artículo: https://docs.microsoft.com/azure/active-directory-b2c/
active-directory-b2c-tutorials-web-app.

Procedimiento
En esta tarea, haremos lo siguiente:

• Configurar Azure AD para la aplicación de función.


• Registrar la aplicación cliente en Azure AD.
• Permitirle a la aplicación cliente que acceda a la aplicación de back-end.
• Probar la funcionalidad de autenticación utilizando un token de JWT.

Configurar Azure AD para la aplicación de función


Lleve a cabo los pasos siguientes:

1. Diríjase a la sección Platform features de Azure Functions.


2. En la hoja Authentication/Authorization, lleve a cabo los pasos siguientes
para habilitar la autenticación de AD:
1. Haga clic en el botón On para habilitar la autenticación.
2. Elija el Inicio de sesión utilizando la opción del menú de Azure
Active Directory.
3. Haga clic en el botón Not Configured para empezar 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 queremos conceder el acceso. Para ello, presione
el botón Express en el campo Management Mode. Además, decidí crear otro
registro de aplicación y le asigné el nombre AzureFunctionCookbookV2.
Haga clic en OK para guardar las configuraciones y luego el sistema lo
dirigirá a la siguiente pantalla.

[ 265 ]
Implementar procedimientos recomendados para Azure Functions

4. Obtenga el ID de aplicación como se muestra. Lo vamos a utilizar durante la


prueba en unos momentos:

Eso es todo. Sin escribir una sola línea de código, terminamos de configurar una
instancia de Azure AD que actúa como un nivel de seguridad y permite el acceso
solo a los usuarios autenticados. En otras palabras,habilitamos OAuth para nuestra
aplicación de función de back-end con Azure AD. Ahora realizaremos una prueba
rápida accediendo a cualquiera de los desencadenadores HTTP que tiene en la
aplicación de función. Para hacer esto, usé Postman. Obtendrá un error pidiéndole
que inicie sesión.

Con las configuraciones actuales, ninguna de las aplicaciones cliente externas podrá
acceder a nuestra API de back-end. Para brindar acceso, tenemos que seguir estos
pasos:

Registre todas las aplicaciones cliente en Azure AD (en este ejemplo, vamos a hacer
un registro para la aplicación Postman).

Conceda acceso a la aplicación de back-end.

Registrar la aplicación cliente en Azure AD


Lleve a cabo los pasos siguientes:

1. Vaya a Azure AD haciendo clic en el botón Azure Active Directory, como


se muestra aquí. Si no lo ve en la lista de favoritos, búsquelo en la hoja All
Services, que también se resalta en la siguiente captura de pantalla:

[ 266 ]
Capítulo 9

2. En el menú AD, haga clic en App Registrations y luego en el botón de


registro New application.
3. Rellene los campos de la siguiente manera y haga clic en el botón Create
para terminar el registro para la aplicación Postman. Debido a que nuestra
aplicación de cliente es Postman, el campo Sign-on URL no nos interesa
demasiado, por lo que http://localhost nos servirá solo para este ejemplo:

[ 267 ]
Implementar procedimientos recomendados para Azure Functions

4. En solo unos instantes, se creará la aplicación y el sistema lo llevará a la


siguiente pantalla. Obtenga el ID de aplicación descrito en Application ID
y guárdelo en el bloc de notas. Lo vamos a utilizar en los próximos pasos.
Haga clic en el botón Settings:

5. En la hoja Settings, haga clic en el elemento de menú Keys para generar


una clave, la cual pasaremos desde Postman. Para generar la clave, primero
tenemos que brindar una descripción en Description y completar el campo
Duration con el plazo de duración después del cual la clave expirará.
Especifique los detalles, como se muestra más abajo en la captura de pantalla,
y haga clic en el botón Save. Veremos la clave real en el campo Value solo
una vez, inmediatamente después de hacer clic en el botón Save. Por lo tanto,
asegúrese de copiarla y almacenarla en un lugar seguro. La utilizaremos a la
brevedad:

[ 268 ]
Capítulo 9

Permitirle a la aplicación cliente que acceda a la


aplicación de back-end
Una vez que la aplicación cliente está registrada, tenemos que concederle acceso
a nuestra aplicación de back-end. En esta sección, aprenderemos a configurarlo:

1. Haga clic en la pestaña Required Permissions y luego en el botón Add, que


muestra la hoja Add API Access, donde tiene que elegir la API requerida
(en este caso, la API de las funciones de Azure de back-end).
2. En la hoja Add API Access, haga clic en el botón Select an API. Al principio,
se muestran las API predeterminadas. Busque su aplicación de back-end
con el nombre que le asignó (en este caso, AzureFunctionCookBookV2).
Seleccione la aplicación de back-end y haga clic en el botón Select.
3. El siguiente paso es proporcionar los permisos reales. Haga clic en la pestaña
Select Permissions y controle el nombre de acceso <Backend App name>.
Luego haga clic en Select y después en el botón Done.
4. Asegúrese de llegar a la siguiente pantalla. También puede hacer clic en el
botón Grant Permission para aplicar los cambios:

Probar la funcionalidad de autenticación utilizando


un token de JWT
Para probar la funcionalidad con Postman, debe tener los siguientes parámetros
configurados:

1. Punto de conexión del token de OAuth 2.0. Puede buscarlo en la pestaña


Endpoints de Azure AD y obtener la URL:
°° Tipo de concesión: este es el valor client_credentials codificado
de forma rígida.
°° ID de cliente de la aplicación cliente: lo apuntó en el cuarto paso de
la sección Registrar la aplicación cliente en Azure AD.
[ 269 ]
Implementar procedimientos recomendados para Azure Functions

°° Clave generada para su aplicación cliente: la apuntó en el quinto


paso de la sección Registrar la aplicación cliente en Azure AD.
°° Recurso: recurso al cual necesitamos acceder. Este es el ID de cliente
de la aplicación de back-end que apuntó en el cuarto paso de la
sección Configurar Azure AD para la aplicación de función.

2. Una vez que tenga toda esa información, pase todos los parámetros y realice
una llamada a un inquilino de Azure AD, que devuelve el token de portador
de la siguiente manera:

3. El próximo y último paso es llamar al back-end real (el desencadenador


HTTP de la función de Azure). Para ello, pase el token de JWT de portador
(access_token) que copió en la pantalla anterior:

[ 270 ]
Capítulo 9

4. Como figura en esta captura de pantalla, agregue el encabezado


Authorization y pegue el token de JWT. Recuerde especificar la palabra del
portador de texto.

Configuración de la limitación de Azure


Functions utilizando API Management
En los capítulos anteriores, aprendimos que podemos utilizar desencadenadores
HTTP de Azure Functions como API web de back-end. Si desea restringir la
cantidad de solicitudes de las aplicaciones cliente a, por ejemplo, 10 solicitudes por
segundo, es posible que tenga que desarrollar una gran lógica. Gracias a Azure API
Management, no es necesario escribir ninguna lógica personalizada si integra Azure
Functions con API Management.

En esta tarea, aprenderemos a restringir el acceso a la API de los clientes solo una vez
por minuto para una dirección IP determinada. Estos son 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 utilizando directivas de entrada.
4. Probar la configuración de las directivas de entrada para el límite
de velocidad.

[ 271 ]
Implementar procedimientos recomendados para Azure Functions

Preparación
Para empezar, tenemos que crear un servicio Azure API Management a través de
estos pasos:

1. Busque API Management y especifique todos estos detalles. En el ejemplo


a continuación, elegí el plan de tarifa Developer. Sin embargo, para las
aplicaciones de producción, elija los planes que no son para desarrolladores
(Basic/Standard/Premium), ya que el plan Developer (No SLA) no brinda
ningún contrato de nivel de servicio (SLA). Revise todos los detalles y haga
clic en el botón Create:

[ 272 ]
Capítulo 9

2. En el momento de la redacción de este libro, el sistema tarda alrededor de


30 minutos para crear una instancia de API Management. Después de crearla,
puede verla en la hoja de servicios API Management:

Procedimiento...
Para aprovechar las capacidades de API Management, es preciso integrar los puntos
de conexión de servicio (en este caso, los desencadenadores HTTP que creamos) con
el servicio API Management. En esta sección se detallan los pasos necesarios para la
integración. Comencemos a integrar ambos servicios.

Integrar Azure Functions con API Management


Lleve a cabo los pasos siguientes:

1. Desplácese a la hoja de API de la instancia API Management Instance que


creó y haga clic en el mosaico Function App.
2. En la ventana emergente Create from Function App, haga clic en el botón
Browse, con lo cual se abrirá una barra lateral con el mosaico Import Azure
Functions. Allí puede configurar las aplicaciones de función. Haga clic en el
botón Configure Required Setting para ver todas las aplicaciones de función
que poseen desencadenadores HTTP. Después de seleccionar la aplicación de
función, haga clic en el botón Select.

[ 273 ]
Implementar procedimientos recomendados para Azure Functions

3. El próximo paso es elegir el desencadenador HTTP que desea integrar con


Azure API Management. Después de hacer clic en el botón Select, como se
menciona en el paso anterior, aparecerán todos los desencadenadores HTTP
asociados con la aplicación de función seleccionada, como se ilustra más
abajo. Para simplificar el procedimiento, elegí un solo desencadenador HTTP:

[ 274 ]
Capítulo 9

4. Una vez que realice todos los pasos anteriores, aparecerá la ventana
emergente Create from Function App que se incluye a continuación.
Revise los detalles y haga clic en el botón Create:

5. Si todo va bien, aparecerá la siguiente captura de pantalla. Ya terminamos de


integrar Azure Functions con API Management:

[ 275 ]
Implementar procedimientos recomendados para Azure Functions

Configurar la limitación de solicitudes utilizando


directivas de entrada
Lleve a cabo los pasos siguientes:

1. Como figura en la captura de pantalla anterior, elija la operación necesaria


(GET) y haga clic en el enlace del editor de directivas de entrada (enumerado
como 3) para abrir el editor de directivas.

API Management nos permite controlar el comportamiento de las


API de back-end (en este caso, desencadenadores HTTP) utilizando
directivas de API Management. Puede controlar las respuestas de
solicitud de entrada y de salida. Puede obtener más información
sobre este tema en https://docs.microsoft.com/azure/api-
management/api-management-howto-policies.

2. Como necesitamos restringir la tasa de solicitudes dentro de API


Management antes de enviar la solicitud a la aplicación de función de
back-end, tenemos que configurar el límite de velocidad en la política de
entrada. Cree una nueva directiva, 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. Finalmente, establezca la clave contraria a la
dirección IP de la aplicación cliente:

[ 276 ]
Capítulo 9

Con esta directiva de entrada, le ordenamos a API Management


que restrinja una solicitud por minuto para una dirección IP
determinada.

3. Un último paso antes de probar la limitación es publicar la API. Para


ello, diríjase a la pestaña Settings en el paso anterior y asocie la API
con un producto publicado (en este caso, tengo un producto de inicio
predeterminado que ya está publicado). Como se observa en la captura
de pantalla más abajo, elija el producto correspondiente y haga clic en el
botón Save:

Los productos en API Management son un grupo de API al que pueden


suscribirse los desarrolladores de distintas aplicaciones cliente. Para
obtener más información sobre los productos de API Management,
consulte https://docs.microsoft.com/azure/api-management/api-
management-howto-add-products.

[ 277 ]
Implementar procedimientos recomendados para Azure Functions

Probar la configuración de las directivas de entrada


para el límite de velocidad
Lleve a cabo los pasos siguientes:

1. Vaya a la pestaña Test y agregue los parámetros o encabezados necesarios


que espera el desencadenador HTTP. En este caso, mi desencadenador HTTP
requiere un parámetro denominado Name.
2. Ahora haga clic en el botón Send que aparece cuando completa el paso
anterior para realizar su primera solicitud. Después de obtener una respuesta
del back-end, aparece algo similar a esto:

3. Luego vuelva a hacer clic inmediatamente en el botón Send. Como se


muestra aquí, el sistema arroja un error. Esto se debe a que nuestra regla de
directivas de entrada es permitir solamente una solicitud por minuto para
una dirección IP determinada:

[ 278 ]
Capítulo 9

Funcionamiento...
En esta tarea, creamos una instancia de Azure API Management e integramos
una aplicación de función de Azure para aprovechar las características de API
Management. Una vez integrados, creamos una directiva de entrada que restringe
a los clientes a solo una llamada por minuto desde una dirección IP determinada. En
este diagrama de alto nivel que ilustra el proceso completo:

[ 279 ]
Implementar procedimientos recomendados para Azure Functions

Acceso seguro a SQL Database desde


Azure Functions utilizando Managed
Service Identity
En una de nuestras tareas, Interacciones de Azure SQL Database con Azure
Functions, del Capítulo 3, Integración perfecta de Azure Functions con los servicios de
Azure, aprendimos a obtener acceso a una base de datos SQL y sus objetos de Azure
Functions proporcionando la cadena de conexión (nombre de usuario y contraseña).

Supongamos que, por alguna razón, cambia la contraseña de una cuenta, lo que
significa que las aplicaciones que utilicen esa cuenta no podrán obtener acceso.
Como desarrollador, ¿no sería bueno tener una instalación en la que no tenga
que preocuparse por las credenciales y, en su lugar, el marco se encargue de la
autenticación? En esta tarea, aprenderemos a obtener acceso a una instancia de SQL
Database desde una función de Azure sin proporcionar un ID de usuario ni una
contraseña utilizando una característica denominada Managed Service Identity.

En el momento de redactar esta tarea, 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). Cuando
esté leyendo este libro, quizá ya esté disponible en la versión más reciente
del marco de trabajo de .NET Core, por lo que esta tarea debería funcionar
también con el tiempo de ejecución de las funciones de Azure v2.

Preparación
Para esta tarea, es preciso crear funciones de Azure (con el tiempo de ejecución de la
v1) y la base de datos de SQL en el mismo grupo de recursos. Si no las creó, hágalo
y regrese a esta tarea para continuar. En esta tarea, llevaremos a cabo los pasos
siguientes:

1. Crear una aplicación de función utilizando Visual Studio 2017 con el tiempo
de ejecución de la v1.
2. Crear un servidor SQL Server lógico y una base de datos SQL.
3. Habilitar Managed Service Identity desde el portal.
4. Recuperar información de Managed Service Identity utilizando la CLI de
Azure.
5. Permitir el acceso de SQL Server a la nueva identidad de servicio
administrada.
6. Ejecutar el desencadenador HTTP y realizar una prueba.

[ 280 ]
Capítulo 9

Procedimiento...
Vamos a realizar esta tarea siguiendo estos pasos:

1. Crear una aplicación de función utilizando Visual Studio 2017 con el tiempo
de ejecución de la v1.
2. Crear un servidor SQL Server lógico y una base de datos SQL.
3. Habilitar Managed Service Identity.

Crear una aplicación de función utilizando Visual


Studio 2017 con el tiempo de ejecución de la v1
Lleve a cabo los pasos siguientes:

1. Para crear una nueva aplicación de función, elija el tiempo de ejecución de las
funciones de Azure v1.
2. Una vez creado el desencadenador HTTP, sustituya 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.
[ 281 ]
Implementar procedimientos recomendados para Azure Functions

windows.net,1433;Initial Catalog=database;Persist Security Info=Fa


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 que copié en el Capítulo 3, Integración perfecta de Azure
Functions con los servicios de Azure, con los cambios especificados más abajo, pero la
cadena de conexión no tiene detalles de ID de usuario ni contraseña.

1. Agregue una nueva línea de código para recuperar el token de acceso:


con.AccessToken = (new AzureServiceTokenProvider()).
GetAccessTokenAsync("https://database.windows.net/").Result;

2. Agregue estos paquetes de NuGet a la aplicación de función:


Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
Install-Package Microsoft.Azure.Services.AppAuthentication
[ 282 ]
Capítulo 9

3. Una vez que compruebe que no hay errores de compilación, publique


la aplicación de función en Azure. Este paso garantiza que creemos la
aplicación de función con el tiempo de ejecución de la v1. Haga clic en el
botón Publish y se abrirá esta ventana emergente:

4. A continuación, especifique el grupo de recursos en Resource Group


y demás detalles, que se ilustran en la siguiente captura de pantalla, y haga
clic en el botón Create:

[ 283 ]
Implementar procedimientos recomendados para Azure Functions

Crear un servidor SQL Server lógico y una base


de datos SQL
Cree un servidor SQL Server y una base de datos SQL en el mismo grupo de recursos
donde creó la aplicación de función de Azure. En este caso, el nombre del grupo de
recursos es AzureServerlessCookbookv1.

Habilitar Managed Service Identity


Lleve a cabo los pasos siguientes:

1. Vaya a las características en Platform de la aplicación de función y haga clic


en Managed service identity.
2. En la pestaña Managed service identity, haga clic en On y Save, como
vemos aquí:

Recuperar información de Managed Service Identity


Lleve a cabo los pasos siguientes:

1. Autentique la identidad de su cuenta de Azure utilizando la CLI de Azure.


Para ello, ejecute el comando az login en el símbolo del sistema, como se
observa aquí:

2. El sistema le pedirá que proporcione las credenciales de su cuenta de


Azure para iniciar sesión en el portal de Azure. Después de brindar sus
credenciales, verá las suscripciones disponibles en la consola de comandos.

[ 284 ]
Capítulo 9

3. Ahora tenemos que recuperar los detalles 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 configuró correctamente la identidad administrada, aparecerá una pantalla


similar a la que se muestra más abajo como salida del comando anterior:

5. Apunte la información de principalId, que se recupera en el paso anterior.


La vamos a utilizar en la próxima sección.

Permitir el acceso de SQL Server al nuevo servicio


identidad administrada
En esta sección, vamos a crear un usuario administrador con acceso al servidor SQL
Server que creamos antes:

1. Ejecute el siguiente comando en el símbolo del sistema pasando el ID en


principalId que apuntó 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 este comando, se crea un nuevo usuario administrador en la base


de datos maestra de SQL Server.
3. Cree una tabla llamada EmployeeInfo con el script a continuación:
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 ) )

[ 285 ]
Implementar procedimientos recomendados para Azure Functions

Ejecutar el desencadenador HTTP y realizar una prueba


Lleve a cabo los pasos siguientes:

1. Abra Postman y envíe una solicitud, como se muestra aquí:

2. Vamos a verificar la base de datos de SQL para ver si el registro se insertó:

[ 286 ]
Capítulo 9

Aún hay más...


Compruebe que tenga todos estos espacios de nombres en la clase:
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;

Consulte también
Consulte la tarea Interacciones de Azure SQL Database con Azure Functions del Capítulo 3,
Integración perfecta de Azure Functions con los servicios de Azure.

Código compartido entre las funciones


de Azure utilizando bibliotecas de clases
Aprendimos a reutilizar un método llamado Helper dentro de una aplicación
de función de Azure. Sin embargo, no puede reutilizarlo 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 tarea, vamos a desarrollar y crear un nuevo archivo. dll
y aprenderá a utilizar las clases y sus métodos en Azure Functions.

[ 287 ]
Implementar procedimientos recomendados para Azure Functions

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree una nueva aplicación Class Library utilizando Visual Studio. En este
caso, usé Visual Studio 2017:

2. Cree un nuevo método de clase llamado Helper y pegue el siguiente código


en el nuevo archivo de clase:
namespace Utilities
{
public class Helper
{
public static string GetReusableFunctionOutput()
{
return "This is an output from a Resuable Library
across functions";
}
}
}

3. Cambie Build Configuration a Release y compile la aplicación para crear el


archivo .dll, que utilizaremos en las funciones de Azure.
4. Diríjase a App Service Editor en la aplicación de función. Para esto, haga
clic en el botón App Service Editor ubicado debajo de Platform Features.

[ 288 ]
Capítulo 9

5. Ahora cree una nueva carpeta Bin haciendo clic derecho en el área vacía
debajo de los archivos ubicados en WWWROOT.
6. Después de hacer clic en el elemento New Folder en la pantalla a la que llegó,
aparece un nuevo cuadro de texto donde tiene que especificar el nombre Bin.
7. A continuación, haga clic derecho en la carpeta Bin y seleccione la opción
Upload Files para cargar el archivo .dll que creó en Visual Studio.
8. Después de cargar el archivo .dll en la carpeta Bin, aparecerá esto:

9. Navegue a la función de Azure donde desea utilizar el método compartido.


Para fines de demostración, creé dos funciones de Azure (un desencadenador
HTTP y un desencadenador de temporizador):

[ 289 ]
Implementar procedimientos recomendados para Azure Functions

10. Desplácese hasta la función ReusableMethodCaller1 y haga los siguientes


cambios:
°° Agregue una nueva directiva #r, como se detalla más abajo, al
método run.csx de la función de Azure ReusableMethodCaller1.
Observe que la extensión .dll es necesaria en este caso:
#r "../bin/Utilities.dll"

°° Agregue un nuevo espacio de nombres, como se indica


a continuación:
using Utilities;

11. Ahora estamos listos para utilizar el método compartido


GetReusableFunctionOutput en la función de Azure. Reemplace el código
del desencadenador HTTP por el siguiente:
log.LogInformation(Helper.GetReusableFunctionOutput());

12. Al ejecutar la aplicación, aparecerá el siguiente mensaje en los registros:

13. Repita los mismos pasos para agregar la referencia y el espacio de nombres
de la biblioteca de utilidades, incluso en la segunda función de Azure,
ReusableMethodCaller2. Si realizó los cambios de forma correcta, debiera
aparecer algo como lo siguiente:

Funcionamiento...
Acabamos de crear un archivo .dll, el cual contiene el código reutilizable que
se puede utilizar en cualquiera de las funciones de Azure que requieren la
funcionalidad disponible mediante el archivo .dll.

Después de generar el archivo .dll, creamos la carpeta Bin en la aplicación de


función y le agregamos el archivo .dll.

[ 290 ]
Capítulo 9

Recuerde que agregamos la carpeta Bin en WWWROOT para que


esté disponible para todas las funciones de Azure disponibles en la
aplicación de función.

Aún hay más...


Si desea emplear el código compartido en una sola función, agregue la carpeta bin
junto con el archivo .ddl en la carpeta de la función de Azure correspondiente.

Otra ventaja importante de utilizar bibliotecas de clases es que mejora el


rendimiento, ya que están compiladas y listas para su ejecución.

Uso de clases fuertemente tipadas en


Azure Functions
En los primeros capítulos, desarrollamos un desencadenador HTTP llamado
RegisterUser que actúa como una API web y puede ser consumido por cualquier
aplicación capaz de realizar solicitudes de HTTP. Sin embargo, para otros requisitos,
puede haber diferentes aplicaciones que creen mensajes en una cola con los detalles
necesarios para crear un usuario. Para hacerlo más simple, utilizaremos el explorador
de Azure Storage para crear un mensaje de cola.

En esta tarea, aprenderemos a obtener la información del usuario desde la cola


utilizando objetos fuertemente tipados.

Preparación
Antes de avanzar, lleve a cabo los pasos siguientes:

1. Cree una cuenta de almacenamiento (yo creé azurefunctionscookbook ) en


la suscripción de Azure.
2. Instale el explorador de Microsoft Azure Storage, si aún no lo hizo.
3. Después de crear el explorador de Storage, conéctese con su cuenta de
almacenamiento de Azure.

[ 291 ]
Implementar procedimientos recomendados para Azure Functions

Procedimiento...
Lleve a cabo los pasos siguientes:

1. A través del explorador de Azure Storage, cree una cola llamada


registeruserqueue en la cuenta de almacenamiento denominada
azurefunctionscookbook. Suponemos que las demás aplicaciones crearán
mensajes en la cola registeruserqueue.
2. Vaya a Azure Functions y cree una nueva función de Azure utilizando el
desencadenador de Azure Queue Storage. Luego elija la cola que creamos.
3. Es posible que el sistema le pida que instale extensiones de almacenamiento,
si aún no lo hizo. Una vez que instale las extensiones, proporcione los
detalles de la cola y haga clic en el botón Create, como se muestra en la
siguiente captura de pantalla:

4. Una vez creada la función, sustituya el código predeterminado por el código


detallado más abajo. Cada vez que se crea un mensaje de cola, el mensaje
JSON se deserializa de manera automática y se rellena en un objeto llamado
myQueueItem. En el siguiente código, solo imprimimos los valores de los
objetos en la ventana Logs:

[ 292 ]
Capítulo 9

using System;
public static void Run(User myQueueItem, ILogger log)
{

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. Diríjase al el explorador de Azure Storage y cree un nuevo mensaje en
registeruserqueue, como se muestra aquí:

[ 293 ]
Implementar procedimientos recomendados para Azure Functions

6. Haga clic en OK para crear el mensaje de cola y regrese a la función de Azure


para observar los registros, como se ve aquí:

Funcionamiento...
Acabamos de desarrollar una nueva función de cola que se desencadena cuando
se agrega un nuevo mensaje a la cola. También creamos un nuevo mensaje de cola
con toda la información necesaria para crear el usuario. Puede seguir reutilizando
el código de la función de Azure para pasar el objeto de usuario (en este caso,
myQueueItem) a la clase de la capa de base de datos, capaz de insertar la información
en una base de datos o en cualquier otro medio persistente.

Aún hay más...


En esta tarea, el tipo de parámetro de mensaje de cola que aceptó el método Run fue
User. El tiempo de ejecución de las funciones de Azure se encargará de deserializar
el mensaje JSON disponible en la cola en el tipo personalizado. En este caso, user.

[ 294 ]
Configurar aplicaciones
sin servidor en el entorno
de producción
En este capítulo, aprenderemos a realizar las siguientes tareas:

• Implementación de Azure Functions con Run From Package.


• Implementación de la función de Azure utilizando plantillas de ARM.
• Configuración de un dominio personalizado en Azure Functions.
• Técnicas para acceder a la configuración de aplicaciones.
• Creación y generación de especificaciones de API abiertas utilizando
Swagger.
• Descomposición de grandes API en pequeños subconjuntos de API
utilizando proxies.
• Migración de elementos de configuración de un entorno a otro utilizando
recursos.

Introducción
Estuvimos analizando cada una de las diferentes características de Azure Functions
que ayudan a los desarrolladores a crear aplicaciones de back-end con rapidez. Este
capítulo se centra en las configuraciones que se necesitan hacer en un entorno de no
desarrollo (como staging, UAT y producción).

[ 295 ]
Configurar aplicaciones sin servidor en el entorno de producción

Implementación de Azure Functions con


Run From Package
Aprendimos diferentes técnicas para desarrollar Azure Functions e implementarla
en la nube.
Como ya debe saber, cada aplicación de función puede tener varias funciones
hospedadas en ella. El código relacionado con esas funciones se ubica en la carpeta
D:\home\site\wwwroot:

El tiempo de ejecución busca en la ubicación D:\home\site\wwwroot


los archivos binarios y todos los archivos de configuración necesarios para ejecutar
la aplicación.
En esta tarea, aprenderemos otra técnica nueva, denominada Run From Package
(también llamada Run From Zip) para implementar la función de Azure como
un paquete.
[ 296 ]
Capítulo 10

Con Run From Package, podemos cambiar la ubicación predeterminada a una cuenta
de almacenamiento externa.

Preparación
Para completar esta receta, necesitamos lo siguiente:

1. Tener instalada la solución Visual Studio 2017 en el equipo local del


desarrollador. Emplee Visual Studio para crear una o más funciones
de Azure. Para este ejemplo, creé un desencadenador HTTP y un
desencadenador de temporizador:

2. Cree una aplicación de función vacía a través del portal de administración


de Azure:

3. Una cuenta de almacenamiento, donde cargaremos el archivo de paquete.


[ 297 ]
Configurar aplicaciones sin servidor en el entorno de producción

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Cree un archivo de paquete para la aplicación. Utilice la misma aplicación


que creó en el Capítulo 4, Comprender la experiencia integrada de desarrollador
de Visual Studio Tools.
2. Vaya a la ubicación donde se encuentra la carpeta bin junto con otros
archivos relacionados con sus funciones. Cree un archivo .zip a partir de los
archivos, como se resalta en la siguiente captura de pantalla:

3. Cree un contenedor de blobs (con acceso privado) y cargue el archivo


de paquete desde el portal o utilizando el explorador de Azure Storage.
4. El próximo paso es generar el token de firma de acceso compartido (SAS)
para el contenedor de blobs, de modo que el tiempo de ejecución de la
función de Azure tenga los permisos necesarios para acceder a los archivos
ubicados en el contenedor. Puede obtener más información sobre SAS en
https://docs.microsoft.com/azure/storage/common/storage-dotnet-
shared-access-signature-part-1:

5. Desplácese a la sección Application settings de la aplicación de función que


creó y genere una nueva configuración de aplicación con la clave WEBSITE_
RUN_FROM_PACKAGE y el valor de Blob SAS URL que creó en el paso anterior,
como se muestra aquí. Haga clic en Save para guardar los cambios:

[ 298 ]
Capítulo 10

6. Eso es todo. Después de la configuración anterior, puede probar la función:

Funcionamiento...
Cuando el tiempo de ejecución de la función de Azure encuentra una configuración
de aplicación con el nombre WEBSITE_RUN_FROM_PACKAGE, entiende que debe buscar
los paquetes en la cuenta de almacenamiento. Por lo tanto, el tiempo de ejecución
descarga los archivos sobre la marcha y los utiliza para iniciar la aplicación.

Aún hay más...


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

Implementación de la función de Azure


utilizando plantillas de ARM
Hasta ahora, aprovisionamos manualmente las funciones de Azure utilizando
el portal de administración de Azure.

En esta tarea, aprenderemos a automatizar el proceso de aprovisionar la función


de Azure utilizando las plantillas de Azure Resource Manager (ARM).

Preparación
Antes de empezar a crear las plantillas de ARM, necesitamos comprender los demás
servicios de Azure de los que depende la función de Azure. Los siguientes servicios
se crean automáticamente al crear una aplicación de función:

[ 299 ]
Configurar aplicaciones sin servidor en el entorno de producción

Como se muestra en la captura de pantalla anterior, la aplicación de función (en este


caso, azurefunctioncookbook-gateway) depende de un plan de App Service y una
cuenta de almacenamiento:
• Plan de App Service: puede ser un plan de App Service ordinario o un plan
de consumo.
• Storage account: el tiempo de ejecución de la función de Azure emplea la
cuenta de Storage para registrar información de diagnóstico que podemos
utilizar para solucionar problemas.
• Application Insights: una cuenta de Application Insights opcional. Si no
estamos utilizando Application Insights, necesitamos crear una configuración
de aplicación con el nombre AzureWebJobsDashboard en la configuración
de aplicación de la función que utiliza el servicio de tablas de Azure Storage
para registrar información de diagnóstico.
Junto con estos servicios, también tenemos que tener un grupo de recursos. En esta
tarea, vamos a suponer que el grupo de recursos ya existe.

Procedimiento...
Hasta ahora, sabe que al crear funciones de Azure tenemos que asegurarnos
de también incluir un plan de App Service y una cuenta de almacenamiento.
Comencemos a crear la plantilla de ARM con Visual Studio:
1. Cree un nuevo proyecto eligiendo Visual C# | Cloud y luego elija Azure
Resource Group:

[ 300 ]
Capítulo 10

2. Al hacer clic en el botón OK en el paso, se abre Select Azure Template


donde tiene que elegir las plantillas Azure QuickStart (github.com/Azure/
azure-quickstart-templates):

3. Busque la palabra function y haga clic en la plantilla 101-function-app-


create-dynamic para crear la aplicación de función de Azure con el plan
de consumo:

[ 301 ]
Configurar aplicaciones sin servidor en el entorno de producción

4. La plantilla JSON necesaria se creará en Visual Studio. Puede obtener más


información acerca del contenido JSON en https://docs.microsoft.com/
azure/azure-functions/functions-infrastructure-as-code.
5. Implemente la plantilla de ARM para aprovisionar la aplicación de función
y sus recursos dependientes. Para ello, haga clic derecho en el nombre del
proyecto (en este caso ARMTemplateforFunctionApp), haga clic en Deploy
y luego en el botón New:

6. Elija los parámetros Subscription, Resource group y demás parámetros para


aprovisionar la aplicación de función. Elija todos los campos obligatorios
y haga clic en el botón Deploy:

[ 302 ]
Capítulo 10

7. ¡Eso es todo! En unos minutos, se iniciará la implementación y se


aprovisionarán cada uno de los recursos mencionados en las plantillas
JSON de ARM:

Aún hay más...


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, de modo que podamos mantener las versiones
de los archivos para realizar un seguimiento de todos los cambios.
• También permite crear servicios en diferentes entornos rápidamente.
• Asimismo, podemos insertar plantillas de ARM en canalizaciones de CI/CD
para automatizar el aprovisionamiento para entornos adicionales.

Configuración de un dominio
personalizado en Azure Functions
A esta altura, si observa la dirección URL predeterminada en el formato
functionappname.azurewebsites.net de la aplicación de función de Azure,, quizá
se pregunte si es posible tener un dominio independiente en lugar del dominio
predeterminado, ya que los clientes pueden tener sus propios dominios. Sí, es posible
configurar un dominio personalizado para las aplicaciones de función. En esta tarea,
aprenderá a configurarlo.

[ 303 ]
Configurar aplicaciones sin servidor en el entorno de producción

Preparación
Cree un dominio con cualquiera de los registradores de dominios. También puede
comprar un dominio directamente desde el portal empleando el botón Buy Domain
ubicado en la hoja Custom Domains:

Una vez que el dominio esté listo, cree los siguientes registros DNS con el registrador
de dominios:

• Registro A
• Registro CName

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Navegue hasta la hoja Custom domains de la aplicación de función de Azure


para la cual desea configurar un dominio:

[ 304 ]
Capítulo 10

2. Si creó un dominio desde el portal de Azure, el sistema le pedirá que elija


nombres de host, como se muestra en la hoja App Service Domain:

[ 305 ]
Configurar aplicaciones sin servidor en el entorno de producción

3. Si eligió ambos, eso es todo. El portal de administración de Azure se


encarga casi por completo de integrar la aplicación de función y el dominio
predeterminado. Puede ver la integración de los nombres de host aquí:

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


existente
Si ya tiene un dominio personalizado y desea integrarlo con la aplicación de función,
debe crear los siguientes dos registros en el DNS:

1. Cree un registro A y un registro CNAME en el registrador de dominios.


Puede obtener la dirección IP de la hoja Custom Domains:

[ 306 ]
Capítulo 10

2. Vaya a la hoja Custom Domains de la aplicación de función y cree los


siguientes nombres de host:

Eso es todo. Acaba de integrar un dominio personalizado con la aplicación


de función de Azure. Ahora puede examinar la aplicación de función con el nuevo
dominio en lugar del dominio predeterminado que presenta Azure:

[ 307 ]
Configurar aplicaciones sin servidor en el entorno de producción

Técnicas para acceder a la configuración


de aplicaciones
En cada aplicación, hay unos pocos elementos de configuración que no convienen
codificar de forma rígida. En su lugar, queremos que cambien en el futuro, después
de que la aplicación se ponga en marcha, sin tocar el código.

En general, los elementos de configuración se clasifican en dos categorías:

• Algunos elementos de configuración pueden ser diferentes en cada entorno;


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 ciertos cálculos del código.

Más allá del uso que le demos al valor de configuración, es importante almacenarlo
en un lugar accesible para su aplicación.

En esta tarea, aprenderemos cómo y dónde almacenar estos elementos de


configuración y diferentes técnicas para acceder a ellos desde el código de la
aplicación.

Preparación
Cree una función de Azure con el tiempo de ejecución de la función v2, si aún no lo
hizo. Voy a utilizar la aplicación de función que creamos en el Capítulo 4, Comprender
la experiencia integrada del desarrollador de Visual Studio Tools.

Procedimiento...
En esta tarea, abordaremos 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 la función de
Azure
Lleve a cabo los pasos siguientes:

1. Cree un elemento de configuración con la clave MyAppSetting y una cadena


de conexión ConnectionStrings con la clave sqldb_connection en el
archivo local.settings.json, que debe asemejarse a la siguiente captura
de pantalla:

[ 308 ]
Capítulo 10

2. Reemplace el código existente por el código detallado más abajo.


Añadimos 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");
}
}

[ 309 ]
Configurar aplicaciones sin servidor en el entorno de producción

3. Publique el proyecto en Azure. Para ello, haga clic derecho en el proyecto


y luego haga clic en Publish en el menú.
4. Agregue la clave de configuración y la cadena de conexión en la hoja
Application Settings:

5. Para ejecutar la función, haga clic en el botón Run, con lo cual se registra
la salida en la ventana Output:

[ 310 ]
Capítulo 10

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


En la sección anterior, aprendimos a acceder a los ajustes de configuración desde
el código. A veces, también es necesario configurar algunos de los elementos
declarativos. Y eso se logra utilizando la expresión de enlace. Comprenderá lo que
quiero decir en un momento cuando observemos el código:

1. Abra Visual Studio y modifique el método Run con el fin de agregar


un nuevo parámetro para configurar QueueTrigger:

2. El parámetro hardcodedqueuename es el nombre de la cola para la cual


se crearán los mensajes. Está claro que codificar de forma rígida el nombre
de la cola no es recomendable. Para que sea configurable, necesitamos
la expresión de enlace de la configuración de aplicación:

3. La clave de configuración de la aplicación debe estar enmarcada por %...%


y se debe crear una clave con el nombre queuename en Application Settings.

Creación y generación
de especificaciones de API abiertas
utilizando Swagger
El desarrollador de API web de back-end tiene la responsabilidad de proporcionar
la documentación adecuada a los desarrolladores de aplicaciones de front-end para
que puedan consumir las API sin ningún problema. Para consumir cualquier API,
es preciso comprender dos cosas mínimas:

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


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

[ 311 ]
Configurar aplicaciones sin servidor en el entorno de producción

Sin embargo, brindar la documentación adecuada para las API no es fácil,


ya que existen muchas herramientas y estándares o especificaciones disponibles
para proporcionar la documentación adecuada de las API de REST. Uno de
estos estándares es la especificación de API abiertas (popularmente conocida
como Swagger).

Azure Functions nos brinda la compatibilidad de herramientas necesaria para


generar las definiciones de API abiertas para nuestros desencadenadores HTTP.
En esta tarea, aprenderemos a generarlas.

Preparación
Cree una función y uno o varios desencadenadores HTTP. Para simplificar la tarea,
creé una aplicación de función y un desencadenador HTTP, que solo acepta métodos
Get.

Tenga en cuenta que en el momento de la redacción, la


característica de definición de API únicamente es compatible
con el tiempo de ejecución de las funciones de Azure v1.0 y aún
continúa en versión preliminar. Todavía no funciona con v2.0.

Asegúrese de que la aplicación de función de Azure esté configurada según


la versión 1 del tiempo de ejecución, como se muestra en Application Settings:

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a Platform features y haga clic en la pestaña API definition:

[ 312 ]
Capítulo 10

2. En la pestaña API definition, haga clic en la opción Function (preview)


para habilitar el origen de la definición de API:

3. Tan pronto como haga clic en el botón Function (preview), se habilitará


la característica. Sin embargo, es posible que vea un error en la nueva pestaña
que se abre. No se preocupe, ya que la característica está todavía en versión
preliminar. Microsoft quizá lo solucione antes de que esté generalmente
disponible (GA). A continuación, haga clic en Generate API definition
template:

[ 313 ]
Configurar aplicaciones sin servidor en el entorno de producción

4. Con esto solo se crea una plantilla para la definición de API abierta.
El desarrollador de la nube debe rellenar la plantilla en función de las API
que desarrolló. Debería verse algo como esto. Vamos a cambiar la plantilla
en un momento:

5. En la captura de pantalla anterior, la pestaña del código contiene todas las


plantillas predeterminadas necesarias para generar la definición de Swagger
a partir de la especificación de API abiertas. En la sección derecha se muestra
el aspecto de la IU de Swagger. La IU de Swagger se compartirá con los
demás equipos de desarrollo de aplicaciones cliente que consumen las API
de back-end.
6. Ahora reemplacemos la plantilla predeterminada. Para ello, agregue
los parámetros solicitados de las operaciones de la API y haga clic en
el botón Save para guardar los cambios. Para simplificar la tarea, hice
algunos cambios que describen la API y sus operaciones. Debería ser fácil
de entender.
7. La IU de Swagger tendrá el siguiente aspecto con los mensajes apropiados
junto con los formatos de solicitud y respuesta:

[ 314 ]
Capítulo 10

8. También nos permite realizar algunas pruebas. Haga clic en el botón Try
this operation que aparece en la captura de pantalla anterior. Se abrirá una
ventana donde se pueden especificar datos de entrada:

[ 315 ]
Configurar aplicaciones sin servidor en el entorno de producción

9. Ingresé Praveen Kumar como valor para el nombre, hice clic en el botón
Send Request y obtuve los siguientes datos de salida:

Descomposición de grandes API


en pequeños subconjuntos de API
utilizando proxies
Últimamente, una de las palabras de moda en la industria es microservicios, donde
se desarrollan los componentes web como microservicios que se pueden administrar
(escalado, implementación, etcétera) de forma individual sin afectar los demás
componentes relacionados. Aunque el tema de los microservicios es muy amplio,
intentaremos crear algunos que se puedan administrar de manera individual como
aplicaciones de función independientes. Sin embargo, los expondremos al mundo
exterior como una API única con diferentes operaciones con la ayuda de los proxies
de la función de Azure.

Preparación
En esta tarea, vamos a implementar la siguiente arquitectura:

[ 316 ]
Capítulo 10

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 construir una API de back-end en una arquitectura de microservicios donde cada
microservicio sea independiente de los demás.

En esta tarea, lograremos esto creando las siguientes aplicaciones de función:

• Un componente de gateway (aplicación de función) que controle el tráfico


al microservicio adecuado según la ruta /men, /women y /kids). En esta
aplicación de función, estamos creando proxies de la función de Azure que
redireccionarán el tráfico utilizando configuraciones de ruta.
• Tres nuevas aplicaciones de función en las que cada una de ellas se trate
como un microservicio independiente.

Procedimiento...
En esta tarea, vamos a seguir estos pasos:

1. Crear los tres microservicios con un desencadenador HTTP en cada uno


de ellos.
2. Crear, establecer el proxy y configurar el microservicio respectivo.
3. Probar la dirección URL del proxy.

[ 317 ]
Configurar aplicaciones sin servidor en el entorno de producción

Crear microservicios
Lleve a cabo los pasos siguientes:

1. Cree tres aplicaciones de función para cada uno de los microservicios


que planificamos:

2. Cree los siguientes desencadenadores HTTP anónimos en cada una de las


aplicaciones de función que muestren un mensaje similar a este:

Nombre del
Mensaje de salida
desencadenador HTTP
Hello <<Name>> - Welcome to the Men
Men-HttpTrigger
Microservice
Hello <<Name>> - Welcome to the
Women-HttpTrigger
Women Microservice
Hello <<Name>> - Welcome to the
Kids-HttpTrigger
Kids Microservice

Crear los proxies de gateway


Lleve a cabo los pasos siguientes:

1. Navegue a la aplicación de función de gateway y cree un nuevo proxy:

[ 318 ]
Capítulo 10

2. El sistema lo llevará a la hoja Details:

[ 319 ]
Configurar aplicaciones sin servidor en el entorno de producción

3. Cree los proxies para mujeres y niños. Estos son los detalles de los tres
proxies. Es posible que las direcciones URL de back-end (de las aplicaciones
de función) sean diferentes en su caso:

Nombre de Plantilla URL de back-end (las URL de los desencadenadores


proxy de ruta HTTP creados en el paso anterior)
Hombres /Men https://azurefunctioncookbook-men.
azurewebsites.net/api/Men-HttpTrigger
Mujeres /Women https://azurefunctioncookbook-women.
azurewebsites.netapi/Women-HttpTrigger
Niños /Kids https://azurefunctioncookbook-kids.
azurewebsites.netapi/Kids-HttpTrigger

4. Una vez que cree los tres proxies, la lista se parecerá a esta:

5. En la captura de pantalla anterior, puede ver tres dominios diferentes. Sin


embargo, si desea compartirlos con las aplicaciones cliente, no es necesario
que comparta estas direcciones URL. Todo lo que tiene hacer es compartir la
URL de los proxies que puede ver en la pestaña Proxy. Estas son las URL de
proxy de los tres proxies que creamos:

• https://azurefunctioncookbook-gateway.azurewebsites.net/Men
• https://azurefunctioncookbook-gateway.azurewebsites.net/Women
• https://azurefunctioncookbook-gateway.azurewebsites.net/Kids

[ 320 ]
Capítulo 10

Probar las URL de proxy


Como ya sabe, los desencadenadores HTTP aceptan un parámetro name requerido
y debemos pasar la cadena de consulta name a la URL de proxy. Accedamos a las
siguientes URL en el explorador:

• Hombres:

• Mujeres:

• Niños:

Observe las URL de las tres capturas de pantalla. Se dará cuenta de que funcionan
desde una única aplicación con diferentes rutas. Sin embargo, son tres microservicios
diferentes que se pueden administrar por separado.

Aún hay más...


Todos los microservicios que creamos en esta tarea son anónimos, lo que significa
que son de acceso público. Para que sean seguros, es preciso seguir alguno de los
enfoques recomendados en el Capítulo 9, Implementar procedimientos recomendados para
Azure Functions.

[ 321 ]
Configurar aplicaciones sin servidor en el entorno de producción

Los proxies de función de Azure también le permiten interceptar la solicitud original


y, si es necesario, puede agregar nuevos parámetros y pasarlos a la API de back-end.
Del mismo modo, puede agregar parámetros adicionales y devolver la respuesta a
la aplicación cliente. Puede conocer más información sobre los proxies de la función
de Azure en los documentos oficiales detallados en https://docs.microsoft.com/
azure/azure-functions/functions-proxies.

Consulte también
• La tarea Controlar el acceso a las funciones de Azure utilizando claves de función
en el Capítulo 9, Implementar procedimientos recomendados para Azure Functions
• La tarea Proteger las funciones de Azure utilizando Azure AD en el Capítulo 9,
Implementar procedimientos recomendados para Azure Functions
• La tarea Configurar la limitación de Azure Functions utilizando API Management
en el Capítulo 9, Implementar procedimientos recomendados para Azure Functions

Migración de elementos de configuración


de un entorno a otro utilizando recursos
Cada una de las aplicaciones que desarrolle tiene muchos elementos de
configuración (p. ej., configuración de aplicación como cadena de conexión) que
se almacenan en archivos Web.Config para todas las aplicaciones web basadas
en .NET.

En el entorno local tradicional, el archivo Web.Config se encuentra en el servidor


y todas las personas con acceso al servidor pueden acceder él. Aunque se pueden
cifrar todos los elementos de configuración de Web.Config, esta tarea tiene sus
limitaciones y no es sencillo cifrarlos cada vez que quiera consultarlos o actualizarlos.

En el entorno de PaaS de Azure, con Azure App Services, también puede tener
archivos Web.Config que funcionan de la misma manera que en el entorno local
tradicional. Sin embargo, Azure App Service nos proporciona una característica
adicional en términos de configuración de la aplicación, donde puede configurar
estas opciones (ya sea manualmente o a través de plantillas de ARM) que se
almacenan en un formato cifrado. Si tiene acceso, puede verlas como texto normal
en el portal.

[ 322 ]
Capítulo 10

Según el tipo de aplicación, la cantidad de configuraciones de aplicación puede


aumentar en gran medida y, si desea crear nuevos entornos, generar estos ajustes
llevaría mucho tiempo. En esta tarea, aprenderemos un método para exportar e
importar estas configuraciones de aplicación de un entorno más bajo (p. ej., Dev)
a uno más alto (p. ej., Prod).

Preparación
Lleve a cabo los pasos siguientes:

1. Cree una aplicación de función (por ejemplo, MyApp-Dev), si aún no lo hizo.


2. Cree algunas configuraciones de aplicación:

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

En esta tarea, aprenderemos lo fácil que es copiar la configuración de la aplicación


de una función a otra. Esta técnica es muy útil para cuando hay muchas
configuraciones de aplicación.

[ 323 ]
Configurar aplicaciones sin servidor en el entorno de producción

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Vaya a la pestaña Platform features de la aplicación de función MyApp-Dev


y haga clic en Resource Explorer:

2. Con Resource Explorer abierto, puede atravesar todos los elementos internos
de un servicio determinado:

[ 324 ]
Capítulo 10

3. Haga clic en el elemento config, como se muestra en la captura de pantalla


anterior, para que se abran todos los elementos relacionados con las
configuraciones:

4. Resource Explorer muestra todas las configuraciones de la aplicación


en la ventana derecha. Ahora puede editarlas haciendo clic en el botón
Edit, resaltado en la captura de pantalla anterior, o copiar todas las
configuraciones de la aplicación de AppSetting0 a AppSetting 9.

[ 325 ]
Configurar aplicaciones sin servidor en el entorno de producción

5. Diríjase a la aplicación de función MyApp-Prod (donde no estarán las


configuraciones de la aplicación resaltadas en la captura de pantalla
más arriba), haga clic en Resource Explorer y luego en los elementos
config | appsettings para abrir las configuraciones de la aplicación actuales.
Debería verse algo como esto:

6. Haga clic en el botón Edit y pegue el contenido que copió antes. Después
de repasar las configuraciones, haga clic en PUT, que se muestra en la
captura de pantalla anterior.

[ 326 ]
Capítulo 10

7. Navegue hasta la hoja de configuración de la aplicación en la aplicación


de función MyApp-Prod:

Allí puede ver todas las configuraciones de la aplicación juntas que creamos
en Resource Explorer.

[ 327 ]
Implementar y facilitar
la integración continua
utilizando Azure DevOps
En este capítulo, aprenderá a hacer lo siguiente:

• Integración continua: crear una definición de compilación.


• Integración continua: poner en cola una compilación y desencadenarla de
forma manual.
• Configuración y desencadenamiento de una compilación automatizada.
• Integración continua: ejecutar casos de prueba unitaria en la canalización.
• Creación de una definición de versión.
• Desencadenamiento de la versión automáticamente.

Introducción
Como profesional de software, es posible que ya conozca las distintas metodologías
de desarrollo de software que aplican las personas. Más allá de la metodología que se
emplee, siempre hay varios entornos, como desarrollo, almacenamiento provisional
y producción, donde se debe seguir el ciclo de vida de la aplicación con estas etapas
fundamentales 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 (dev/storage/prod).

[ 329 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

4. Probar para comprobar que se cumplan los requisitos.


5. Promover la publicación al siguiente entorno (de Dev a Stage y de Stage
a Prod).

Tenga en cuenta que para hacerlo más simple, se excluyeron las etapas
iniciales, como la reunión de requisitos, la planificación, el diseño
y la arquitectura, para hacer hincapié en las etapas relevantes para este
capítulo.

Para cada cambio que realice en el software, es necesario compilar e implementar la


aplicación en varios entornos y suele suceder que diferentes equipos se encargan de
publicar las compilaciones en cada uno de los entornos. Debido a que intervienen
distintos entornos y equipos, y teniendo en cuenta la cantidad de tiempo dedicado
a ejecutar las compilaciones, implementarlas en diferentes entornos dependerá más
de los procesos que adopten los distintos equipos.

Con el fin de agilizar y automatizar algunos de los pasos mencionados antes, en este
capítulo, analizaremos algunas de las técnicas populares que sigue la industria para
entregar software rápidamente, con una infraestructura mínima.

En los capítulos anteriores, la mayoría de las tareas aportaron una


solución para un problema comercial individual. Sin embargo, a lo
largo de todo este capítulo, se intentará brindarle una solución para
la integración y entrega continua de su aplicación crítica para el
negocio.

El equipo de Azure DevOps agrega, de manera constante, nuevas características


a Azure DevOps en https://dev.azure.com (antes conocido como VSTS en
https://www.visualstudio.com), además de actualizar la interfaz de usuario.
Mientras lee estas instrucciones, no se alarme si las capturas de pantalla que se muestran
en este capítulo no coinciden con las que usted ve en https://dev.azure.com.

Requisitos previos
Cree lo siguiente, si aún lo hizo:

1. Cree una organización de Azure DevOps, la que prefiera, en


https://dev.azure.com y cree un nuevo proyecto en esa cuenta. Mientras
crea el proyecto, puede elegir entre las opciones GIT o Team Foundation
Version Control como repositorio de control de versiones. Para mi proyecto,
usé Team Foundation Version Control:

[ 330 ]
Capítulo 11

2. Configure el proyecto de Visual Studio que desarrolló en el Capítulo 4,


Comprender la experiencia integrada del desarrollador de Visual Studio Tools para
Azure Functions, en Azure DevOps. Puede consultar el enlace https://www.
visualstudio.com/en-us/docs/setup-admin/team-services/set-up-vs
para seguir el proceso paso a paso para crear una nueva cuenta
y un nuevo proyecto utilizando Azure DevOps.

Voy a hacer algunos pequeños cambios en los mensajes de respuesta


incrustados en el código para mostrar diferentes salidas. Asegúrese
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
Una definición de compilación es un conjunto de tareas necesarias para configurar
una compilación automatizada del software. En esta tarea, realizaremos lo siguiente:

• Crear la plantilla de la definición de compilación.


• Proporcionar todas las entradas necesarias para cada uno de los pasos para
crear la definición de compilación.

[ 331 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Preparación
Siga estos requisitos previos:

1. Cree una cuenta de Azure DevOps.


2. Cree un proyecto con la opción Team Foundation Version Control, como
se ilustra aquí:

[ 332 ]
Capítulo 11

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Diríjase a la pestaña Pipelines en la cuenta de Azure DevOps, haga clic en


Builds y elija New pipeline para comenzar a crear una nueva definición de
compilación, como figura aquí:

2. En el próximo paso, haga clic en el enlace Use a visual designer, de esta


manera:

[ 333 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

3. El sistema lo llevará a la pantalla Select your repository, donde puede elegir


el repositorio que desee. En este ejemplo, elegí el origen TFVC. Como se
muestra a continuación, seleccione TFVC y haga clic en Continue. Asegúrese
de elegir el proyecto, que en este caso es AzureServerlessCookBook:

4. Luego avanzará al paso Select a template, donde puede elegir la plantilla


adecuada para su aplicación. En esta tarea, vamos a elegir C# Function,
como se observa más abajo. Para ello, haga clic en el botón Apply:

[ 334 ]
Capítulo 11

5. El proceso de creación de una compilación comprende un conjunto de pasos


que sirven para definir la plantilla de compilación, donde cada paso tiene
determinados atributos que tenemos que revisar y debemos proporcionar
entradas para cada uno de esos campos en función de nuestros requisitos.
Para empezar, especifique un nombre significativo en el paso de canalización
y asegúrese de elegir Hosted VS2017 en el menú desplegable Agent Pool,
como se muestra en la siguiente captura de pantalla:

Un agente es un software hospedado en la nube capaz de


ejecutar una compilación. Como nuestro proyecto se basa
en VS2017, elegimos Hosted VS2017.

[ 335 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

6. En el paso Get sources, seleccione lo siguiente:


1. Seleccione el sistema de control de versiones que le gustaría tener.
2. Elija el repositorio que quiere compilar. En este ejemplo, elegí
AzureServerlessCookBook:

7. Deje las opciones predeterminadas en estos pasos:


°° Utilice NuGet and NuGet restore: este paso es necesario para
descargar e instalar todos los paquetes requeridos para la aplicación.
°° Build solution: este paso emplea MS Build y posee todos los
comandos predefinidos para crear la compilación.
°° Test assemblies: este paso sería de mucha utilidad si tuviéramos
pruebas automatizadas. Vamos a incorporar algunos cambios en este
paso en la tarea Integración continua: ejecutar casos de prueba unitaria en
la canalización más adelante en este capítulo.
°° Archive files: este paso nos permite archivar las carpetas en el
formato requerido.
°° Publish symbols path: estos símbolos sirven para depurar la
aplicación hospedada en la VM del agente.
°° Publish artifact: este paso contiene la configuración relacionada con
los artefactos y la ruta para almacenarlos (paquete de compilaciones).

8. Una vez que revise cada uno de los valores en todos los campos, haga clic en
Save, como se muestra en la siguiente captura de pantalla, y vuelva
a hacer clic en Save en la ventana emergente para guardar la definición de
compilación:

[ 336 ]
Capítulo 11

Funcionamiento...
Una definición de compilación es solo un plano técnico de las tareas necesarias
para compilar una aplicación de software. En esta tarea, utilizamos una plantilla
predeterminada para crear la definición de compilación. También podemos elegir
una plantilla en blanco y crear la definición eligiendo las tareas disponibles en Azure
DevOps.

Cuando se ejecuta la definición de compilación (ya sea de forma manual


o automática, que se abordará en las recetas posteriores), cada una de las tareas se
ejecutará en el orden en que se configuraron. Asimismo, puede reorganizar los pasos
arrastrándolos y soltándolos en la sección de canalización.

Al comienzo, el proceso de compilación obtiene el código fuente del repositorio


elegido y descarga los paquetes de NuGet necesarios. Luego inicia el proceso
de compilación del paquete. Una vez completado ese proceso, crea un
paquete y lo almacena en una carpeta configurada para el directorio build.
artifactstagingdirectory (consulte el campo Path to publish de la tarea
Publish artifact).

Puede obtener información sobre los diferentes tipos de variables en la pestaña


Variables que se muestra aquí:

[ 337 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Aún hay más...


• Azure DevOps proporciona muchas tareas. Puede elegir una nueva tarea
para la plantilla haciendo clic en el botón Add Task (+), como figura aquí:

• Si no encuentra una tarea que se adapte a sus requisitos, busque la adecuada


en el Marketplace. Para ello, haga clic en el botón Marketplace que aparece
en la captura de pantalla anterior.
• Asimismo, la función de C# posee el conjunto correcto 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 de forma
manual
En la tarea anterior, aprendió a crear y configurar la definición de compilación. En
esta tarea, aprenderá a desencadenar la compilación manualmente y comprender el
proceso de compilación de la aplicación.

Preparación
Antes de comenzar, asegúrese de que realizó lo siguiente:

• Configurar la definición de compilación como se mencionó en la tarea


anterior.
• Todo el código fuente está protegido en el proyecto del equipo de Azure
DevOps.

[ 338 ]
Capítulo 11

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Desplácese a la definición de compilación llamada


AzureServerlessCookBook-C# Function-CI y haga clic en el botón Queue
en el extremo derecho, como se muestra aquí:

2. En la ventana emergente Queue build for AzureServerlessCookBook-C#


Function-CI, compruebe que esté marcada la opción Hosted VS2017 en el
menú desplegable Agent pool si está utilizando Visual Studio 2017 y haga
clic en el botón Queue, como vemos aquí:

[ 339 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

3. En unos instantes, la compilación se pondrá en cola y se mostrará el mensaje,


como se ilustra en la siguiente captura de pantalla:

4. Para iniciar el proceso, haga clic en build ID (en este caso, 20181025.1). El
sistema aguardará unos segundos para que un agente disponible lo inicie.
5. Después de un momento, se inicia el proceso de compilación y, en tan solo
unos minutos, la compilación se completa. Puede revisar los pasos de la
compilación en los registros, como se muestra aquí. Por ahora, descarte la
advertencia que aparece para Test Assemblies. Lo solucionaremos en la
tarea Integración continua: ejecutar casos de prueba unitaria en la canalización más
adelante en este capítulo:

[ 340 ]
Capítulo 11

6. Si desea consultar la salida de la compilación, haga clic en el botón Artifacts


que se resalta en la siguiente captura de pantalla. Para descargar los archivos,
haga clic en el botón Download como se muestra aquí:

Configuración y desencadenamiento de
una compilación automatizada
Para la mayoría de las aplicaciones, no tiene sentido realizar compilaciones manuales
en Azure DevOps. Sí lo tendría si pudiéramos configurar la integración continua
(CI) automatizando el proceso para desencadenar la compilación para cada una de
las comprobaciones o confirmaciones que realicen los desarrolladores.

En esta tarea, aprenderá a configurar la integración continua en Azure DevOps


para su proyecto de equipo y también a desencadenar la compilación automatizada
realizando un cambio en el código de la función de Azure del desencadenador HTTP
que creamos en el Capítulo 4, Comprender la experiencia integrada del desarrollador de
Visual Studio Tools para Azure Functions.

[ 341 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Vaya a la definición de compilación AzureServerlessCookBook-C#


Function-CI haciendo clic en el botón Edit como se observa en esta captura
de pantalla:

2. Cuando se encuentre allí, haga clic en el menú Triggers, como se describe


aquí:

3. Ahora haga clic en la casilla Enable continuous integration para habilitar el


desencadenador de compilación automatizada.
4. Para guardar los cambios, haga clic en la flecha ubicada junto al botón Save
& queue y luego haga clic en el botón Save del menú desplegable, como
vemos aquí:

[ 342 ]
Capítulo 11

5. Vayamos al proyecto de Azure Functions en Visual Studio. Realice un


pequeño cambio en la última línea del código de función Run que se muestra
a continuación. Tan solo reemplacé la palabra hello por Automated Build
Trigger test by:
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 comprobar el código y confirmar los cambios en el control de


código fuente. Como se muestra aquí, se genera un nuevo ID de conjunto de
cambios. En este caso, es Changeset 32:

7. Ahora, regrese a la definición de compilación de Azure DevOps para ver que


una nueva compilación se desencadenó automáticamente y está en curso,
como se muestra aquí:

[ 343 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Funcionamiento...
Estos son los pasos que se siguieron en esta tarea:

1. Habilitamos el desencadenador de compilación automática para la definición


de compilación.
2. Hicimos un cambio en el código base y lo comprobamos en TFVC.
3. Se desencadenó automáticamente una nueva compilación en Azure DevOps.
La compilación sucede tan pronto como el código se confirma en TFVC.

Aún hay más...


Si desea restringir a los desarrolladores para que comprueben en código solo
después de una compilación correcta, debe habilitar la inserción en el repositorio
validada. Para ello, edite la definición de compilación y vaya a la pestaña Triggers
y Enable gated check-in, como se ilustra aquí:

Ahora vuelva a Visual Studio y realice algunos cambios en el código. Si intenta


comprobar el código sin compilar la aplicación desde Visual Studio, obtendrá una
alerta, como vemos aquí:

[ 344 ]
Capítulo 11

Haga clic en Build Changes en el paso anterior para iniciar la compilación en Visual
Studio. Apenas se complete la compilación en Visual Studio, el código se comprobará
en Azure DevOps y, a continuación, se activará una nueva compilación de forma
automática, como se muestra aquí:

Integración continua: ejecutar casos de


prueba unitaria en la canalización
Uno de los pasos más importantes en cualquier metodología de desarrollo de
software es escribir pruebas unitarias automatizadas que validen la exactitud de
nuestro código. También es importante ejecutar estas pruebas unitarias cada vez que
el desarrollador publique un código nuevo, para proporcionar cobertura de código
de prueba.

En esta tarea, aprenderemos a incorporar el proceso de compilación de las pruebas


unitarias que desarrollamos en la tarea Desarrollar pruebas unitarias para las funciones
de Azure con desencadenadores HTTP del Capítulo 5, Explorar las herramientas de prueba
para validar las funciones de Azure.

[ 345 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Procedimiento...
Lleve a cabo los pasos siguientes:

1. En la tarea Integración continua: crear una definición de compilación de este


capítulo, empleamos una plantilla de compilación que comprendía los pasos
Build solution y Test Assemblies, como se muestra aquí:

2. Haga clic en Test Assemblies, como figura en la captura de pantalla anterior.


Reemplace la configuración predeterminada por la que se detalla aquí, en el
campo Test files:
**\$(BuildConfiguration)\**\*test*.dll
!**\obj\**
!**\*TestAdapter.dll

3. Los ajustes de configuración anteriores permiten al ejecutor de pruebas hacer


lo siguiente:
°° Buscar los archivos .dll que contengan la palabra Test en su
nombre y se encuentren en la carpeta release en alguna parte de los
artefactos. Quizá se pregunte por qué empleamos release. Porque
es el valor de la variable $(BuildConfiguration) en la sección
Variables que se incluye en esta captura de pantalla:

[ 346 ]
Capítulo 11

°° Pase por alto todos los archivos .dll en la carpeta obj, ya que
nuestro objetivo es trabajar únicamente en los archivos .dll situados
en la carpeta release.
4. Eso es todo. Ahora vamos a poner en cola la compilación. Para hacerlo,
haga clic en el botón Queue después de guardar los cambios. Luego de unos
minutos, la canalización de compilación se pasa sin advertencias, como se
muestra en la siguiente captura de pantalla:

[ 347 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

5. Aquí está el resumen de los casos de prueba. Puede ver el gráfico con el
porcentaje de los casos de prueba superados y no superados:

Aún hay más...


Si respetó todas las convenciones de nomenclatura según las instrucciones, no tendrá
ningún problema en esta tarea. Sin embargo, si utilizó un nombre diferente para
el proyecto unitario y no empleó la palabra test en alguna parte del nombre del
proyecto (que es el mismo nombre que el archivo .dll generado), puede cambiar el
formato en la siguiente configuración:
**\$(BuildConfiguration)\**\*whateverwordyouhaveinthenameofthedllfi
le*.dll

En la tarea, usó *, ** y !, que se denominan "patrones de coincidencia de archivos".


Puede 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.

Creación de una definición de versión


Ahora que sabemos cómo crear una definición de compilación y desencadenar
una compilación automatizada en Azure DevOps (canalizaciones), el siguiente
paso consiste en publicar o implementar el paquete en un entorno donde las partes
interesadas del proyecto puedan revisarlo y brindar comentarios. Para ello, primero
tenemos que crear una definición de versión de la misma manera en que creamos las
definiciones de compilación.

[ 348 ]
Capítulo 11

Preparación
Usé el nuevo editor de definiciones de versión para visualizar las canalizaciones
de implementación. El editor de definiciones de versión aún continúa en versión
preliminar. Para cuando lea esto, si todavía sigue en versión preliminar, habilítelo
haciendo clic en la imagen de perfil y luego en el enlace Preview features, como se
muestra aquí:

De esta forma, podrá habilitar el nuevo editor de definiciones de versión, como


vemos en la siguiente captura de pantalla:

Comencemos a crear una nueva definición de versión.

[ 349 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Procedimiento...
Lleve a cabo los pasos siguientes:

1. Vaya a la pestaña Releases, que se muestra en la captura de pantalla más


abajo, y haga clic en el enlace New Pipeline:

2. Luego elija una plantilla en Release definition. En la ventana emergente


Select a template, seleccione Azure App Service deployment y haga clic en
el botón Apply, como vemos aquí: Inmediatamente después de hacer clic en
el botón Apply, aparece una nueva ventana emergente Environment (etapa).
Por ahora, cierre la ventana emergente Environment:

[ 350 ]
Capítulo 11

3. Haga clic en el botón Add ubicado en el cuadro Artifacts para agregar un


nuevo artefacto, como se muestra en esta captura de pantalla:

[ 351 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

4. En la ventana emergente Add an artifact, elija lo siguiente:


1. Source type: Build.
2. Project: el proyecto de equipo con el que está vinculado su código
fuente.
3. Source (build definition): el nombre de la definición de compilación
donde están creadas las compilaciones.
4. Default Version: Latest.

5. Repase todos los valores en la página y haga clic en el botón Add para
agregar el artefacto.
6. El siguiente paso es configurar las etapas donde el paquete debe publicarse.
Haga clic en el enlace 1 phase, 1 task, como se ilustra aquí: Además, cambie
el nombre de la definición de la versión a release-def-stg:

[ 352 ]
Capítulo 11

7. El sistema lo llevará a la pestaña Tasks, que se incluye más abajo. Brinde


un nombre significativo para el campo Stage name. En este ejemplo, usé el
nombre Staging Environment. A continuación, elija la suscripción de Azure
en la que quiere implementar la función de Azure. Haga clic en el botón
Authorize para especificar los permisos, como vemos aquí:

[ 353 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

8. Después de autorizar la suscripción, asegúrese de haber configurado App


type como Function App. Luego elija el nombre de la aplicación de función
en el nombre de App Service, incluido en App Service name, donde desea
implementar el paquete, como se ilustra aquí:

Si no ve la suscripción o el servicio de aplicaciones,


actualice el elemento haciendo clic en el ícono ubicado
a continuación del botón Authorize en la captura de
pantalla anterior.

9. Haga clic en el botón Save para guardar los cambios. Ahora utilice esta
definición de versión e intente crear la nueva versión. Para hacerlo, haga clic
en Create release, como vemos aquí:

[ 354 ]
Capítulo 11

10. Luego, el sistema lo llevará al elemento emergente Create a new release,


donde puede configurar la definición de compilación que necesita utilizar.
Como tenemos una, vemos solo una definición de compilación. También
debe elegir la versión correcta de la compilación, como se muestra aquí.
Revísela y haga clic en el botón Create para poner en cola la versión:

[ 355 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

11. Al hacer clic en el botón Create en el paso anterior, avanzará al próximo


paso. Haga clic en el botón Deploy stage, como se muestra aquí, para iniciar
el proceso de implementación de la versión:

12. Ahora se le pedirá que revise los artefactos asociados. Cuando termine, haga
clic en el botón Deploy, como vemos aquí:

[ 356 ]
Capítulo 11

13. El proceso empieza de inmediato y le muestra el mensaje In Progress que


indica el progreso de la versión, como se ilustra aquí:

[ 357 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

14. Haga clic en los enlaces In Progress que aparecen en la captura de pantalla
anterior para consultar el progreso. El proceso se ejecutó con éxito, como
vemos aquí:

Funcionamiento...
En la pestaña Pipeline, creamos artefactos y un entorno llamado Staging, y los
vinculamos.

También configuramos el entorno para que Azure App Service se relacione con las
funciones de Azure que creamos en el Capítulo 4, Comprender la experiencia integrada
del desarrollador de Visual Studio Tools para Azure Functions.

Aún hay más...


Si esta es la primera vez que configura la implementación continua, aparecerá el
botón Authorize en el paso Azure App Service deployment. Si hace clic en el botón
Authorize, se abre una ventana emergente donde tiene que brindar las credenciales
del portal de administración de Azure.

Puede renombrar la canalización de la versión haciendo clic en el nombre en la parte


superior, como se muestra aquí:

[ 358 ]
Capítulo 11

Actualmente, hay una plantilla específica de Azure Functions, que se muestra


a continuación. Sin embargo, parece que no funciona. Cuando lea este libro, intente
utilizarla:

Consulte también
La tarea Implementar la aplicación de función de Azure en la nube de Azure utilizando
Visual Studio del Capítulo 4, Comprender la experiencia integrada del desarrollador de
Visual Studio Tools para Azure Functions.

[ 359 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

Desencadenamiento de la versión
automáticamente
En esta tarea, aprenderá a configurar la implementación continua para un entorno.
En el proyecto, puede configurar dev/staging o cualquier otro entorno de
preproducción, además de la implementación continua para agilizar el proceso de
implementación.
En general, no se recomienda configurar la implementación continua para un
entorno de producción. Sin embargo, esto depende de varios factores y requisitos.
Tenga cuidado y piense en varios escenarios antes de configurar la implementación
continua para el entorno de producción.

Preparación
Descargue e instale la herramienta Postman, si aún no lo hizo.

Procedimiento...
Lleve a cabo los pasos siguientes:
1. Las versiones están configuradas, de manera predeterminada, para insertarse
manualmente. Vamos a configurar la implementación continua. Regrese
a la pestaña Pipeline y haga clic en el desencadenador de implementación
continua, como se muestra aquí:

[ 360 ]
Capítulo 11

2. Como se ilustra en la captura de pantalla más abajo, habilite el


desencadenador de implementación continua y haga clic en Save para
guardar los cambios:

3. Navegue a Visual Studio y realice algunos cambios en el código, como se


resalta aquí:
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 compruebe el código con un comentario, Continuous Deployment,


para confirmar los cambios en Azure DevOps. Después de comprobar el
código, vaya a la pestaña Builds para ver cómo se desencadena una nueva
compilación, como figura aquí:

[ 361 ]
Implementar y facilitar la integración continua utilizando Azure DevOps

5. Desplácese a la pestaña Releases después de completar la compilación para


comprobar que la nueva versión se desencadena de forma automática, lo cual
se ilustra aquí:

6. Una vez finalizado el proceso de versión, puede revisar el cambio realizando


una solicitud al desencadenador HTTP mediante la herramienta Postman:

Funcionamiento...
En la pestaña Pipeline, habilitamos el desencadenador de implementación
continua.
Cada vez que se desencadena una compilación asociada con
AzureServerlessCookBook-C# Function-CI, la versión Azure Serverless
Cookbook Release se desencadena automáticamente para implementar la
compilación más reciente en el entorno designado. También vimos cómo funciona
la versión automática haciendo un cambio en el código en Visual Studio.

Aún hay más...


También puede crear varios entornos y configurar las definiciones para publicar las
compilaciones necesarias en esos entornos.
[ 362 ]
Otros libros que puede
disfrutar
Si disfrutó este libro, puede que le interesen estos otros libros de Packt:

Architecting Microsoft Azure Solutions – Exam Guide 70-535 (Diseñar soluciones de


Microsoft Azure: Guía de examen 70-535)
Sjoukje Zaal
ISBN: 978-1-78899-173-5
ff Utilice las Máquinas Virtuales de Azure para diseñar implementaciones
de VM efectivas.
ff Implemente estilos de arquitectura, como informática sin servidor y microservicios.
ff Proteja sus datos utilizando diferentes características de seguridad y diseñe
estrategias de seguridad efectivas.
ff Diseñe soluciones de almacenamiento de Azure empleando varias características
de almacenamiento.
ff Cree soluciones de administración de identidades para sus aplicaciones y recursos.
ff Diseñe soluciones de vanguardia con inteligencia artificial, IoT y Azure
Media Services.
ff Utilice diferentes soluciones de automatización incorporadas en la plataforma de Azure.
363
Otros libros que puede disfrutar

Hands-On Linux Administration on Azure (Administración práctica de Linux en Azure)

Frederik Vos

ISBN: 978-1-78913-096-6

ff Comprenda por qué Azure es la solución ideal para sus cargas de trabajo
de open source.
ff Domine las habilidades esenciales de Linux y aprenda a manejar el entorno
de Linux.
ff Implemente Linux en un entorno de Azure.
ff Utilice la administración de configuración para administrar Linux en Azure.
ff Administre contenedores en un entorno de Azure.
ff Mejore la seguridad de Linux y utilice los sistemas de administración
de identidades de Azure.
ff Automatice la implementación con Azure Resource Manager (ARM)
y PowerShell.
ff Emplee Ansible para administrar instancias de Linux en un entorno de nube
de Azure.

364
Otros libros que puede disfrutar

Deje una reseña y permita que otros


lectores conozcan su opinión
Comparta su opinión acerca de este libro con otras personas, dejando una reseña en el
sitio en el que lo compró. Si compró el libro en Amazon, déjenos una reseña sincera en
la página de Amazon donde figura este libro. Esto es esencial para que otros potenciales
lectores puedan ver y utilizar su opinión imparcial para tomar decisiones de compra,
para que nosotros podamos saber lo que nuestros clientes piensan de nuestros productos
y para que nuestros autores vean su opinión acerca del título que han creado junto
a Packt. Dejar su opinión le tomará unos minutos, pero esta será valiosa para otros
clientes potenciales, para nuestros autores y para Packt. ¡Gracias!

365

S-ar putea să vă placă și