Salta a la nube. Creación de una solución de IoT económica en NodeMCU + Azure IoT Hub

El destino más popular para dispositivos IoT es la recolección de telemetría. Hasta la fecha, los precios de los servicios de IoT en la nube han disminuido tanto que incluso un usuario ordinario puede permitirse el lujo de usarlos. Hoy hablaremos sobre cómo enviar datos a la nube desde la placa NodeMCU usando el idioma Lua.



Nota: continuamos la serie de publicaciones de versiones completas de artículos de la revista Hacker. Ortografía y puntuación del autor guardado.


Doy la palabra al autor.


Como trabajo en la pila de tecnología de Microsoft, uso Azure Functions y Table Storage para crear la parte de la nube de la solución IoT, pero mi PoC para NodeMCU y Lua también se puede usar con otros proveedores de soluciones de IoT en la nube.


INFORMACIÓN


Expressif NodeMCU es una de las placas base más asequibles con Wi-Fi, micro USB y un programador integrado. Se basa en el módulo ESP8266. La placa de segunda generación se puede comprar por alrededor de $ 6-7. Puede trabajar con la placa desde el IDE de Arduino. Además, la placa admite un lenguaje de secuencias de comandos llamado Lua (traducido del portugués como "Luna").


Conectar y configurar el dispositivo


Para que el dispositivo sea reconocido en Windows, debe descargar el controlador desde el siguiente enlace: Controladores CP210x USB a UART Bridge VCP


La velocidad del puerto serie estándar de NodeMCU es 115'200bps. Puede establecer una velocidad diferente, en el primer reinicio del dispositivo volverá a 115200.
Es importante que el controlador esté configurado exactamente a la misma velocidad:



Firmware


Lo más probable es que se pierda algo en el firmware inicial, por lo que lo ideal es actualizar el dispositivo usted mismo. Hay varias formas de crear una imagen de firmware. Usar un servicio en la nube , una imagen de Docker o usar instrucciones para Linux . Recolecté usando un servicio en la nube. También te aconsejo esta opción.


Si necesita enviar datos a la nube, las funciones necesarias para la selección son SNTP, MQTT, HTTP (WiFi, temporizador, archivo, GPIO, red, nodo, UART ya están seleccionados de forma predeterminada). También es necesario marcar como requerido el soporte TLS / SSL en Opciones varias
El enlace con el archivo bin llega al correo. Más precisamente, incluso 2 enlaces vienen de inmediato. Uno con una imagen que admite operaciones de punto flotante, y el segundo con una no compatible.


Antes de flashear el ESP8266, debe ponerlo en modo especial. Hay un botón FLASH separado en el tablero. Al presionarlo durante el encendido o al reiniciar, el dispositivo pasa al modo de cargador de arranque. Si de repente no hay tal botón en la modificación de su placa, entonces antes de parpadear necesita conectar GPIO0 a GND y presionar reiniciar (este método es adecuado para ESP-12).


El firmware se puede actualizar con la utilidad PyFlasher . Py en el nombre significa que la aplicación está escrita en Python. También hay nodemcu-flasher , pero no se ha actualizado durante mucho tiempo. No lo he probado


La ventana de PyFlasher se ve así:



El modo de flash se selecciona según la placa que tenga. La mayoría de las placas base modernas basadas en los módulos ESP8266 ESP-12 y ESP32 usan el modo DIO. ESP8266 01 a 07 se ajusta al modo QIO más rápido. DOUT es utilizado por ESP8285.


Configuración IDE


Descargue el IDE gratuito en el enlace de ESPlorer . Alternativamente, hay ZeroBrane Studio . Lo que más me gustó de ESPlorer, así que daré un ejemplo de cómo trabajar con él. ESPlorer está escrito en JAVA. La interfaz de la aplicación es



En el lado izquierdo se encuentra el código, la configuración y alguna otra funcionalidad similar. A la derecha está la ventana de monitoreo y los comandos de administración de dispositivos. Abra la aplicación, seleccione el puerto. Establezca la velocidad a la que se realizará el intercambio (lo más probable es que sea 115200) y haga clic en Abrir.



Para calentar, puede ejecutar un script simple que parpadea con un LED incorporado:


LED = 0 gpio.mode(LED, gpio.OUTPUT) function flash_led() gpio.write(LED, gpio.LOW) tmr.delay(500000) gpio.write(LED, gpio.HIGH) end tmr.alarm(1, 1000, tmr.ALARM_AUTO, flash_led) 

Si su placa no tiene un LED incorporado (o si ya está completamente harto de ejemplos de LED parpadeante =), puede intentar ejecutar un script aún más simple que muestre la línea:


 print("Hello from Lua!") 

Después de crear un archivo .lua (digamos test.lua), agregue el código y guárdelo en el disco, puede descargarlo en su dispositivo. Para hacer esto, abra el puerto si no está abierto (botón Abrir) y haga clic en el botón Cargar. Puede encontrarlo entre los botones que se encuentran debajo del código (a la izquierda).


Después de descargar el archivo, puede ejecutarlo enviando el comando:


 dofile("test.lua") 

El comando se puede ingresar manualmente en el campo inferior ubicado a la derecha debajo del monitor. O, si no desea escribir ningún texto, puede hacer clic en el botón Recargar (la fila extrema de botones a la derecha). Después de hacer clic en este botón, recibirá una lista de botones con los archivos .lua cargados en el tablero. Al hacer clic en el botón con el nombre del archivo, se iniciará la ejecución del archivo.


Si desea que el archivo se inicie inmediatamente después de encender el tablero, cree un archivo llamado init.lua.


Configurar la parte de la nube para trabajar con el dispositivo


Dejemos nuestro dispositivo por un tiempo y creemos su doble en la nube. Recientemente, se puede crear un dispositivo doble directamente en Azure Portal, utilizando la nueva funcionalidad. En el grupo de configuración de IoT Hub llamado Exploradores, debe seleccionar Dispositivos IoT y hacer clic en "+ Agregar"


Para conectar el dispositivo al centro de IoT, necesitamos generar SAS (firma de acceso compartido). Para generar SAS, se usa una doble clave de dispositivo, que se puede obtener usando alguna utilidad auxiliar (Device Explorer, iothub-explorer, IoT Extension para Azure CLI 2.0). Pero la forma más fácil de obtener la clave está allí, en el portal de Azure, yendo al IoT Hub -> Dispositivos IoT.



SAS puede generarse en el dispositivo, o puede generarse utilizando cualquiera de sus servicios en línea. Si usa el SDK, puede generar SAS automáticamente (es suficiente para especificar la doble clave del dispositivo en el código).



La forma en que un token SAS es generado por un servicio web por un cierto tiempo limitado es un poco más seguro. Aunque hay un cierto matiz. Si envía solo el nombre del dispositivo al servicio, alguien puede buscar a través de los nombres para obtener el token de otro dispositivo. Por lo tanto, para que el proceso sea un poco más seguro, propongo esta solución: guardemos el hash de Azure de la doble clave del dispositivo en el dispositivo. Y en el código de servicio, antes de generar el SAS, verificaremos si el hash coincide con el hash de la clave del dispositivo. Por lo tanto, será posible obtener SAS solo conociendo el nombre del dispositivo y el hash de su clave.


La primera forma en que se genera SAS en el dispositivo es más simple y más conveniente, pero un poco menos segura. Dado que, después de obtener acceso al dispositivo, un atacante podrá obtener la clave y generar el dispositivo SAS de forma independiente. En el segundo caso, después de obtener acceso al dispositivo, el cracker podrá recibir solo tokens SAS, cuya vida útil es limitada.


Resulta que ambos métodos son, en general, no ideales si el hacker tiene acceso al dispositivo. Incluso asegurar una conexión usando una VPN no ayudará aquí. En este caso, el canal de transmisión estará protegido, pero aquellos que tengan el dispositivo en sus manos podrán acceder al canal. Desafortunadamente, en dispositivos NodeMCU, Arduino, etc. no hay forma de almacenar claves / contraseñas en ningún almacenamiento seguro. Quizás el mercado de dispositivos IoT de bajo costo requiere una nueva funcionalidad de hardware.


Crear una función de Azure para la generación SAS


Como servicio en línea, es más fácil usar las características de Azure. Estos son fragmentos únicos que se pueden escribir de inmediato en el portal de Azure en el navegador. Bromeando como una broma, pero de esta manera puedes programar incluso desde un teléfono inteligente. Por supuesto, nadie prohíbe crearlos y depurarlos desde Visual Studio, y solo luego publicarlo en Azure en forma compilada.


La tarea de la función es realizar algunas operaciones generalmente no muy complicadas. Según la idea del microservicio, cada función puede hacer una cosa, pero es muy buena (principio de responsabilidad única).


Puede crear una aplicación Azure Function en el portal completando un breve formulario



El Plan de consumo le permite pagar solo por las llamadas de función que se han comprometido. Esta es la opción más barata. Actualmente, un millón de llamadas a funciones son gratuitas.


Tenga en cuenta que junto con la creación de la función, también se crea un almacenamiento de datos auxiliar (Almacenamiento).


Después de crear la aplicación de funciones, puede crear la función en sí. En este caso, necesitamos una función como Webhook + API. La función puede estar abierta a todos (acceso anónimo) y puede estar disponible solo para los propietarios de un código especial. El código se puede obtener desde la ventana con la función haciendo clic en el enlace </> Obtener URL de la función:



Las funciones se pueden escribir en varios idiomas. Prefiero C #.


 using System.Net; using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Common.Security; using System.Globalization; using System.Security.Cryptography; using System.Text; public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { string deviceid = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "deviceid", true, CultureInfo.InvariantCulture) == 0).Value; string hash = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "hash", true, CultureInfo.InvariantCulture) == 0).Value; if (String.IsNullOrEmpty(deviceid)) return req.CreateResponse(HttpStatusCode.BadRequest, "device id missing"); if (String.IsNullOrEmpty(hash)) return req.CreateResponse(HttpStatusCode.BadRequest, "hash missing"); var resourceUri ="ArduinoDemoHub.azure-devices.net/devices/"+deviceid; // taken from IoT Hub user with Connect devices rights (not from Device Explorer) var connectionString = "HostName=ArduinoDemoHub.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=cuYBKc42lfJr4oSRGQGQ8IiKWxGQkLre7rprZDZ/ths="; var registryManager = RegistryManager.CreateFromConnectionString(connectionString); var device = await registryManager.GetDeviceAsync(deviceid); var key = device.Authentication.SymmetricKey.PrimaryKey; HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes("somerandomkeyKJBWyfy4gski")); var hashedkey = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(key))); if (hashedkey!=hash) return req.CreateResponse(HttpStatusCode.BadRequest, "wrong hash"); SharedAccessSignatureBuilder sasBuilder = new SharedAccessSignatureBuilder() { Key = key, Target = resourceUri, TimeToLive = TimeSpan.FromDays(Convert.ToDouble(7)) }; var SAS = sasBuilder.ToSignature(); return req.CreateResponse(HttpStatusCode.OK, SAS); } 

Creamos el archivo project.json y le agregamos los siguientes contenidos:


 { "frameworks": { "net46":{ "dependencies": { "Microsoft.Azure.Devices": "1.4.1" } } } } 

El código usa la cadena de conexión al centro de IoT. Se puede confundir con la cadena de conexión al dispositivo. Para que no se confunda, permítame recordarle dónde puede obtenerlo:



Es necesario tomar la cadena de conexión de alguna política con los derechos de conexión de dispositivo.
Es mejor no especificar la cadena de conexión en el código, como hice. Hice esto solo por el ejemplo. Lo mejor es acceder a la función de configuración de la aplicación



Y especifique la cadena de conexión allí. Después de eso, puede "obtenerlo" de la tienda segura usando


 ConfigurationManager.ConnectionStrings["___"].ConnectionString 

En el dispositivo, necesitamos guardar la clave hash. Pero primero debes codificar los caracteres. HttpUtility.UrlEncode del sistema. El espacio web nos ayudará con esto.


 hashedkey = HttpUtility.UrlEncode(hashedkey); 

Enviaremos la solicitud usando Get, pero no todos los caracteres se pueden pasar como un valor de parámetro.


Escribir código para enviar datos a la nube


Escribí un pequeño código en Lua enviando datos a la nube. El resultado fue una especie de PoC. Puede usarlo y modificarlo según sus necesidades.
Cree 2 archivos init.lua y SendDataToCloud.lua
El contenido de la primera:


 --    print('init.lua ver 1.2') wifi.setmode(wifi.STATION) print('set mode=STATION (mode='..wifi.getmode()..')') print('MAC: '..wifi.sta.getmac()) print('chip: '..node.chipid()) print('heap: '..node.heap()) --  Wifi station_cfg={} station_cfg.ssid="_SSID" station_cfg.pwd="___" station_cfg.save=false wifi.sta.config(station_cfg) wifi_status_codes = { [0] = "Idle", [1] = "Connecting", [2] = "Wrong Password", [3] = "No AP Found", [4] = "Connection Failed", [5] = "Got IP" } sntp_connect_status_codes = { [1] = "DNS lookup failed", [2] = "Memory allocation failure", [3] = "UDP send failed", [4] = "Timeout, no NTP response received" } --    Wi-fi (   ) tmr.alarm(6,1000, 1, function() if wifi.sta.getip()==nil then print("Waiting for IP address! (Status: "..wifi_status_codes[wifi.sta.status()]..")") else print("New IP address is "..wifi.sta.getip()) tmr.stop(6) --    NTP sntp.sync({'pool.ntp.org'}, function(sec, usec, server) print("Clock Synced: "..sec..", "..usec..", "..server) tls.cert.verify(false) --    dofile('SendDataToCloud.lua') end, function(error_code) print("Clock Sync Failed: "..sntp_connect_status_codes[error_code]) end, 1 --      ) end end ) 

Este archivo se conecta a la red y ejecuta el código del archivo SendDataToCloud.lua si la conexión es exitosa.


Debe especificar los datos de su punto de acceso Wi-Fi como los valores de station_cfg.ssid y station_cfg.pwd.


En el siguiente archivo, debe cambiar el nombre del dispositivo y el IoT del concentrador (variables DEVICE e IOTHUB). La variable funcurl contiene la dirección de la función generadora de SAS y el hash de la clave del dispositivo (que codificamos previamente usando HttpUtility.UrlEncode) como el valor del parámetro hash


 --  DEVICE = "LuaDevice" IOTHUB = "ArduinoDemoHub.azure-devices.net" PORT = 8883 USER = "ArduinoDemoHub.azure-devices.net/"..DEVICE.."/api-version=2016-11-14" telemetry_topic="devices/"..DEVICE.."/messages/events/" connected = false local headers = 'Content-Type: application/x-www-form-urlencoded\r\n'.. 'Accept: */*\r\n'.. 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0' funcurl = "https://arduinofunction.azurewebsites.net/api/GenerateSASFunction?code=Jn7j54PbR31BSRa0UZrDwp4ZEltjmWHmblG9zLo0Ne0tyGM7w/wQ7w==" funcurl = funcurl.."&hash=oJzykimyQsTPtzgJxYq90Xfqmw1rZTPTCH%2bJ5sSurKI%3d" funcurl = funcurl.."&deviceid="..DEVICE tmr.alarm(1,5000, 1, function() http.get(funcurl, headers, function(code, data, header) if (code < 0) then print("HTTP request failed") else sas = true print(code, data) if string.match(data, "Shared") then tmr.stop(1) SAS = string.sub(data,2,string.len(data)-1) print(SAS) connect(SAS) end end end) end) function connect(SAS) --   MQTT client = mqtt.Client(DEVICE, 240, USER, SAS) --   IoTHub    MQTT print ("Connecting to MQTT broker. Please wait...") tmr.alarm(2,1000, 1, function() client:connect(IOTHUB, PORT, 1, -- Callback     function(client) tmr.stop(2) print("Connected to MQTT: "..IOTHUB..":"..PORT.." as "..DEVICE) connected = true senddata() end, -- Callback    function(client, reason) print("Error Connecting: "..reason) end ) end) end function senddata() math.randomseed(1) tmr.alarm(3, 1000, tmr.ALARM_AUTO, publish_data) --   ,     callback client:on("offline", function(client) print("MQTT Disconnected.") connected = false end) end --      function publish_data() if connected == true then somedata = math.random(1,100) --     payload = "{ \"deviceId\" : \""..DEVICE.."\",".. "\"iotdata\" :"..somedata.."}" --   client:publish(telemetry_topic, payload, 1, 0, function(client) print("Data published successfully.") end) end end 

Los datos se envían sin usar el SDK de Azure, por lo que puede usar este código no solo para enviar datos a Azure. Hay muchas alternativas: AWS, Google Cloud IoT, IBM Watson IoT Platform.


El ejemplo utiliza el protocolo MQTT (Transporte de telemetría de colas de mensajes). Este es un protocolo abierto diseñado específicamente para dispositivos IoT. Los datos se envían en formato JSON. Cuando en proyectos reales se toman datos de sensores, se genera un número aleatorio en el ejemplo.


Durante el proceso de enlace entre el dispositivo y el centro de IoT, el servidor puede enviar su certificado o puede solicitar un certificado de dispositivo. Si recuerdas, la última vez que trabajamos con el dispositivo Arduino, lo flasheamos con un certificado. Ahora un sumidero de código es suficiente:


 tls.cert.verify(false) 

Estamos limitados al certificado que el servidor nos enviará.


INFORMACIÓN


Puede interesarle el contenido de los certificados para su concentrador utilizando el siguiente comando OpenSSL.


 openssl s_client -showcerts -connect ArduinoDemoHub.azure-devices.net:8883 

Para preparar el material, se utilizaron los laboratorios, que están disponibles en el enlace: Envío de mensajes de dispositivo a la nube (D2C)
El código no está muy actualizado y tuve que actualizarlo un poco, pero en general el enlace puede ser útil.


Trabajando con NodeMCU desde Arduino IDE


No puedo ignorar el tema del uso del SDK. Su solución es buena, pero el SDK es el mismo código que ya está depurado, simplificado y listo para usar. Algunas palabras sobre cómo configurar y usar el IDE de Arduino para trabajar con NodeMCU.


Después de instalar el IDE de Arduino, debe ir al menú Archivo - Preferencias



Y agregue un enlace al administrador de la junta adicional: ingrese en el campo URL del Administrador de la Junta Adicional la dirección: http://arduino.esp8266.com/versions/2.4.0/package_esp8266com_index.json


Luego vaya al menú Herramientas - Tablero xxx - Administrador de Boardx e instale ESP8266
Instale las bibliotecas AzureIoTHub, AzureIoTUtility, AzureIoTProtocol_MQTT. Después de instalar la última biblioteca en los ejemplos (menú Archivo - Ejemplos - AzureIoTProtocol_MQTT), puede encontrar un ejemplo simpleample_mqtt para ESP8266.


El ejemplo está listo para comenzar. Simplemente complete los valores de las variables en el archivo iot_configs.h
Menciono una pequeña desventaja. Compilar el proyecto y descargarlo en el tablero, en comparación con Lua, lleva bastante tiempo.


Guardar datos en la nube de Azure


Con el envío de datos, todo está claro, pero qué tan económico es guardar datos en la nube.
La forma más económica de enviar datos desde el centro de IoT a la base de datos es Azure Functions. Y el almacenamiento de datos más económico es Azure Table Storage.


Curiosamente, cuando crea una aplicación de función, el almacenamiento también se crea automáticamente, que la función en sí misma necesita para funcionar. Si crea un repositorio separado, es aconsejable hacer la configuración básica de la siguiente manera:



La replicación de LSR es actualmente la opción más económica. Se selecciona cuando se crea automáticamente un repositorio vinculado a una función.
Lo que necesitamos ahora es recibir datos del centro de IoT y escribirlos en el almacenamiento. Para este caso, al crear una función, la ventana de Inicio rápido no podrá ofrecernos la opción deseada.



Por lo tanto, haga clic en el enlace de la función personalizada ubicado en la parte inferior y seleccione la opción IoT Hub (Event Hub).
Esta ventana se abrirá para nosotros:



En el que podemos completar el campo de conexión de Event Hub con una opción simple (haciendo clic en nuevo). Pero para indicar el nombre del Event Hub, debe ir al IoT Hub. En el centro, debe ir a Puntos finales (puntos finales) y obtener el nombre compatible con Event Hub desde allí



Pasemos al código de función. El siguiente fragmento recibe datos del centro de IoT y los almacena en Table Storage:


 #r "Microsoft.WindowsAzure.Storage" #r "Newtonsoft.Json" using Microsoft.Azure; // Namespace for CloudConfigurationManager using Microsoft.WindowsAzure.Storage; // Namespace for CloudStorageAccount using Microsoft.WindowsAzure.Storage.Table; // Namespace for Table storage types using Newtonsoft.Json; public static void Run(string myIoTHubMessage, TraceWriter log) { var e = JsonConvert.DeserializeObject<EventDataEntity>(myIoTHubMessage); log.Info($"C# IoT Hub trigger function processed a message: {myIoTHubMessage}"); CloudStorageAccount storageAccount = CloudStorageAccount.Parse ("DefaultEndpointsProtocol=https;AccountName=iotdatademostorage;AccountKey=JgStNcJvlQYeNsVCmpkHQUkWlZiQ7tJwAm6OCL34+lGx3XrR+0CPiY9RoxIDA6VSvMKlOEUrVWL+KWP0qLMLrw==;EndpointSuffix=core.windows.net"); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); CloudTable table = tableClient.GetTableReference("iottable"); table.CreateIfNotExists(); EventDataEntity edata = new EventDataEntity("IOTpartition", Guid.NewGuid().ToString()); edata.DeviceId = e.DeviceId; edata.IotData = e.IotData; TableOperation insertOperation = TableOperation.Insert(edata); table.Execute(insertOperation); } public class EventDataEntity : TableEntity { public EventDataEntity(string pkey, string rkey) { this.PartitionKey = pkey; this.RowKey = rkey; } public EventDataEntity() { } public string DeviceId { get; set; } public int IotData { get; set; } } 

Si va a utilizar este código en un proyecto real, no olvide colocar la cadena de conexión en un lugar más seguro, en la configuración de la aplicación (exactamente igual que la cadena de conexión de la primera función).


La cadena de conexión en sí se puede tomar en el elemento de configuración llamado Teclas de acceso:



Ver el contenido de la tabla con la utilidad gratuita Azure Storage Explorer


Dado que el costo de Azure Table Storage es bastante bajo, y Azure Functions e IoT Hub ofrecen ciertos recursos mensuales de forma gratuita, el costo de la solución completa por mes puede ser inferior a $ 1. Por supuesto, depende de la cantidad de datos. Cuenta por ti mismo. Hoy, 1 GB de datos cuesta 7 centavos por mes y por cada millón de transacciones se le cobrará solo 4 centavos.


INFORMACIÓN


Cuando utilice servicios en la nube de cualquier proveedor, siempre le aconsejo que vincule una tarjeta de crédito con la cantidad mínima de dinero a su cuenta. Es una casualidad que al elegir algún tipo de configuración errónea pague mucho más de lo que espera.


Le recordamos que esta es la versión completa de un artículo de la revista Hacker . Su autor es Alexey Sommer .


Materiales utiles


Guía de arquitectura de aplicaciones en la nube


Adopte un enfoque estructurado para desarrollar aplicaciones en la nube. Este libro electrónico de 300 páginas sobre arquitectura de computación en la nube analiza las pautas de arquitectura, desarrollo e implementación que se aplican independientemente de la plataforma de nube que elija. Esta guía incluye pasos para:


  • Elegir el estilo de arquitectura de aplicaciones en la nube adecuado para su aplicación o solución;
  • selección de tecnologías apropiadas de computación y almacenamiento de datos;
  • implementando 10 principios de desarrollo para crear una aplicación escalable, resistente y manejable;
  • siguiendo los cinco principios de crear software de calidad que garantice el éxito de su aplicación en la nube;
  • Usando patrones de diseño diseñados para el problema que está tratando de resolver.

Descargar


Guía del desarrollador de Azure



En esta actualización de la Guía del desarrollador de Azure, verá cómo el conjunto completo de servicios para la plataforma de software de Azure satisface sus necesidades. Aquí encontrará información sobre enfoques arquitectónicos y las situaciones más comunes que surgen al crear aplicaciones en la nube.


Descargar


Conceptos básicos de Microsoft Azure


Este libro proporciona información importante sobre los servicios clave de Azure para desarrolladores y profesionales de TI que son nuevos en la computación en la nube. Se incluyen demostraciones paso a paso para ayudar al lector a comprender cómo comenzar con cada uno de los servicios clave. Cada capítulo es independiente, no es necesario realizar demostraciones prácticas de capítulos anteriores para comprender un capítulo en particular.


Los siguientes temas están cubiertos en este libro:


  • Comenzando con Azure;
  • Azure Application Service y aplicaciones web;
  • Máquinas virtuales;
  • Servicio de almacenamiento;
  • Bases de datos
  • Servicios adicionales de Azure.

Descargar


Enlaces utiles


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


All Articles