Inicio rápido: creación de una aplicación sin servidor mediante Azure Functions y Azure SignalR Service

Comience a usar Azure SignalR Service, mediante Azure Functions y Python, para compilar una aplicación sin servidor que difunda mensajes a los clientes. La función se ejecutará en el entorno local y se conectará a una instancia de Azure SignalR Service en la nube. Completar este inicio rápido supondrá un pequeño costo en su cuenta de Azure.

Nota

Puede obtener el código en este artículo en GitHub.

Prerrequisitos

Esta guía de inicio rápido se puede ejecutar en macOS, Windows o Linux. Necesitará lo siguiente:

Requisito previo Descripción
Una suscripción de Azure Si no tiene una suscripción de Azure, cree una cuenta gratuita de Azure
Editor de código Necesitará un editor de código como Visual Studio Code.
Azure Functions Core Tools Requiere la versión 2.7.1505 o posterior para ejecutar aplicaciones de funciones de Azure de Python localmente.
Python 3.7+ Azure Functions requiere Python 3.7 o una versión superior. Consulte las versiones de Python que se admiten.
Azurite El enlace de SignalR necesita Azure Storage. Las funciones que se ejecuten localmente pueden usar un emulador de almacenamiento local.
CLI de Azure Opcionalmente, puede usar la CLI de Azure para crear una instancia de Azure SignalR Service.

Creación de una instancia del servicio Azure SignalR

En esta sección, creará una instancia básica de Azure SignalR para su aplicación. En los pasos siguientes se usa Azure Portal para crear una instancia, pero también puede usar la CLI de Azure. Para obtener más información, vea el comando az signalr create en la referencia de la CLI de Azure SignalR Service.

  1. Inicie sesión en Azure Portal.
  2. En la parte superior izquierda de la página, seleccione + Crear un recurso.
  3. En la página Crear un recurso, en el cuadro de texto Search services and marketplace (Servicios de búsqueda y Marketplace), escriba signalr y, después, seleccione SignalR Service en la lista.
  4. En la página SignalR Service, seleccione Crear.
  5. En la pestaña Aspectos básicos, escriba la información esencial para la nueva instancia de SignalR Service. Escriba los siguientes valores:
Campo Valor sugerido Descripción
Suscripción Elija una suscripción Seleccione la suscripción que quiere usar para crear una instancia de SignalR Service.
Grupos de recursos Cree un grupo de recursos denominado SignalRTestResources Seleccione o cree un grupo de recursos para el recurso SignalR. Es útil crear un grupo de recursos para este tutorial en lugar de usar un grupo de recursos existente. Para liberar recursos después de completar el tutorial, elimine el grupo de recursos.

Al eliminar un grupo de recursos también se eliminarán todos los recursos que pertenezcan a él. Esta acción no se puede deshacer. Antes de eliminar un grupo de recursos, asegúrese de que no incluye los recursos que quiere conservar.

Para obtener más información, consulte Uso de grupos de recursos para administrar los recursos de Azure.
Nombre del recurso testsignalr Escriba un nombre de recurso único para usarlo en el recurso SignalR. Si testsignalr ya se ha usado en la región, agregue un dígito o carácter hasta que el nombre sea único.

El nombre debe ser una cadena de entre 1 y 63 caracteres y solo puede contener números, letras y el carácter de guion (-). El nombre no puede empezar ni terminar con el carácter de guion y no se pueden usar varios guiones consecutivos.
Región Elija la región. Seleccione la región adecuada para la nueva instancia de SignalR Service.

Azure SignalR Service no está disponible actualmente en todas las regiones. Para obtener más información, vea Disponibilidad en regiones para Azure SignalR Service.
Plan de tarifa Seleccione Cambiar y luego elija Free (Dev/Test Only) (Gratis (solo desarrollo/pruebas)). Elija Seleccionar para confirmar el plan de tarifa que elija. Azure SignalR Service tiene tres planes de tarifa: Gratis, Estándar y Premium. Los tutoriales usan el nivel Gratis, a menos que se indique lo contrario en los requisitos previos.

Para obtener más información sobre las diferencias de función entre los niveles y los precios, vea Precios de Azure SignalR Service.
Modo de servicio Elección del modo de servicio adecuado Utilice Predeterminado cuando aloje la lógica del concentrador SignalR en sus aplicaciones web y utilice el servicio SignalR como proxy. Use Sin servidor cuando use tecnologías sin servidor, como Azure Functions, para hospedar la lógica del centro de SignalR.

El modo Clásico solo es para la compatibilidad con versiones anteriores y no se recomienda su uso.

Para obtener más información, vea Modo de servicio en Azure SignalR Service.

No es necesario cambiar la configuración en las pestañas Redes y Etiquetas de los tutoriales de SignalR.

  1. Seleccione el botón Revisar y crear de la parte inferior de la pestaña Aspectos básicos.
  2. En la pestaña Revisar y crear, revise los valores y luego seleccione Crear. La implementación tarda unos minutos en completarse.
  3. Cuando se complete la implementación, seleccione el botón Ir al grupo de recursos.
  4. En la página de recursos de SignalR, seleccione Claves en el menú de la izquierda, en Configuración.
  5. Copie la cadena de conexión de la clave principal. Necesitará esta cadena de conexión para configurar su aplicación más adelante en este tutorial.

Crear proyecto de Azure Function

Creación de un proyecto local de Azure Function.

  1. Desde la línea de comandos, cree un directorio para el proyecto.
  2. Cambie al directorio del proyecto.
  3. Use el comando func init de Azure Functions para inicializar el proyecto de función.
# Initialize a function project
func init --worker-runtime python

Creación de las funciones

Después de inicializar un proyecto, tendrá que crear funciones. Este proyecto requiere tres funciones:

  • index: hospeda una página web para un cliente.
  • negotiate: permite que un cliente obtenga un token de acceso.
  • broadcast: usa un desencadenador de tiempo para difundir periódicamente mensajes a todos los clientes.

Al ejecutar el comando func new desde el directorio raíz del proyecto, Azure Functions Core Tools anexa el código de función en el archivo function_app.py. Editará el contenido de anuncios de parámetros según sea necesario reemplazando el código predeterminado por el código de la aplicación.

Creación de la función de índice

Puede usar esta función de ejemplo como plantilla para sus propias funciones.

Abra el archivo function_app.py . Este archivo contendrá las funciones. En primer lugar, modifique el archivo para incluir las instrucciones de importación necesarias y defina las variables globales que usaremos en las siguientes funciones.

import azure.functions as func
import os
import requests
import json 

app = func.FunctionApp()

etag = ''
start_count = 0
  1. Agregue la función index agregando el código siguiente
@app.route(route="index", auth_level=func.AuthLevel.ANONYMOUS)
def index(req: func.HttpRequest) -> func.HttpResponse:
    f = open(os.path.dirname(os.path.realpath(__file__)) + '/content/index.html')
    return func.HttpResponse(f.read(), mimetype='text/html')

Esta función hospeda una página web para un cliente.

Creación de la función negotiate

Agregue la función negotiate agregando el código siguiente

@app.route(route="negotiate", auth_level=func.AuthLevel.ANONYMOUS, methods=["POST"])
@app.generic_input_binding(arg_name="connectionInfo", type="signalRConnectionInfo", hubName="serverless", connectionStringSetting="AzureSignalRConnectionString")
def negotiate(req: func.HttpRequest, connectionInfo) -> func.HttpResponse:
    return func.HttpResponse(connectionInfo)

Esta función permite a un cliente obtener un token de acceso.

Cree una función de difusión.

Agregue la función broadcast agregando el código siguiente

@app.timer_trigger(schedule="*/1 * * * *", arg_name="myTimer",
              run_on_startup=False,
              use_monitor=False)
@app.generic_output_binding(arg_name="signalRMessages", type="signalR", hubName="serverless", connectionStringSetting="AzureSignalRConnectionString")
def broadcast(myTimer: func.TimerRequest, signalRMessages: func.Out[str]) -> None:
    global etag
    global start_count
    headers = {'User-Agent': 'serverless', 'If-None-Match': etag}
    res = requests.get('https://api.github.com/repos/azure/azure-functions-python-worker', headers=headers)
    if res.headers.get('ETag'):
        etag = res.headers.get('ETag')

    if res.status_code == 200:
        jres = res.json()
        start_count = jres['stargazers_count']

    signalRMessages.set(json.dumps({
        'target': 'newMessage',
        'arguments': [ 'Current star count of https://api.github.com/repos/azure/azure-functions-python-worker is: ' + str(start_count) ]
    }))

Esta función usa un desencadenador de hora para difundir periódicamente mensajes a todos los clientes.

Crear proyecto de Azure Function

Creación de un proyecto local de Azure Function.

  1. Desde la línea de comandos, cree un directorio para el proyecto.
  2. Cambie al directorio del proyecto.
  3. Use el comando func init de Azure Functions para inicializar el proyecto de función.
# Initialize a function project
func init --worker-runtime python --model v1

Creación de las funciones

Después de inicializar un proyecto, tendrá que crear funciones. Este proyecto requiere tres funciones:

  • index: hospeda una página web para un cliente.
  • negotiate: permite que un cliente obtenga un token de acceso.
  • broadcast: usa un desencadenador de tiempo para difundir periódicamente mensajes a todos los clientes.

Al ejecutar el comando func new desde el directorio raíz del proyecto, Azure Functions Core Tools creará archivos de origen de función predeterminados y los almacenará en una carpeta denominada como la función. Editará los archivos según sea necesario reemplazando el código predeterminado por el código de la aplicación.

Creación de la función de índice

Puede usar esta función de ejemplo como plantilla para sus propias funciones.

  1. Ejecute el siguiente comando para crear la función index.
func new -n index -t HttpTrigger
  1. Edite index/function.json y reemplace el contenido por el código json siguiente:
{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}
  1. Edite index/_init_.py y reemplace el contenido por el código siguiente:
import os

import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    f = open(os.path.dirname(os.path.realpath(__file__)) + '/../content/index.html')
    return func.HttpResponse(f.read(), mimetype='text/html')

Creación de la función negotiate

  1. Ejecute el siguiente comando para crear la función negotiate.
func new -n negotiate -t HttpTrigger
  1. Edite negotiate/function.json y reemplace el contenido por el código json siguiente:
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    },
    {
      "type": "signalRConnectionInfo",
      "name": "connectionInfo",
      "hubName": "serverless",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "in"
    }
  ]
}
  1. Edite negotiate/_init_.py y reemplace el contenido por el código siguiente:
import azure.functions as func


def main(req: func.HttpRequest, connectionInfo) -> func.HttpResponse:
    return func.HttpResponse(connectionInfo)

Cree una función de difusión.

  1. Ejecute el siguiente comando para crear la función broadcast.
func new -n broadcast -t TimerTrigger
# install requests
pip install requests
  1. Edite broadcast/function.json y reemplace el contenido por el código siguiente:
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "myTimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "*/5 * * * * *"
    },
    {
      "type": "signalR",
      "name": "signalRMessages",
      "hubName": "serverless",
      "connectionStringSetting": "AzureSignalRConnectionString",
      "direction": "out"
    }
  ]
}
  1. Edite broadcast/_init_.py y reemplace el contenido por el código siguiente:
import requests
import json

import azure.functions as func

etag = ''
start_count = 0

def main(myTimer: func.TimerRequest, signalRMessages: func.Out[str]) -> None:
    global etag
    global start_count
    headers = {'User-Agent': 'serverless', 'If-None-Match': etag}
    res = requests.get('https://api.github.com/repos/azure/azure-signalr', headers=headers)
    if res.headers.get('ETag'):
        etag = res.headers.get('ETag')

    if res.status_code == 200:
        jres = res.json()
        start_count = jres['stargazers_count']

    signalRMessages.set(json.dumps({
        'target': 'newMessage',
        'arguments': [ 'Current star count of https://github.com/Azure/azure-signalr is: ' + str(start_count) ]
    }))

Creación del archivo index.html

La interfaz de cliente de esta aplicación es una página web. La función index lee el contenido HTML del archivo content/index.html.

  1. Cree una carpeta denominada content en la carpeta raíz del proyecto.
  2. Cree el archivo content/index.html.
  3. Copie el siguiente contenido en el archivo content/index.html y guárdelo:
<html>

<body>
  <h1>Azure SignalR Serverless Sample</h1>
  <div id="messages"></div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>
  <script>
    let messages = document.querySelector('#messages');
    const apiBaseUrl = window.location.origin;
    const connection = new signalR.HubConnectionBuilder()
        .withUrl(apiBaseUrl + '/api')
        .configureLogging(signalR.LogLevel.Information)
        .build();
      connection.on('newMessage', (message) => {
        document.getElementById("messages").innerHTML = message;
      });

      connection.start()
        .catch(console.error);
  </script>
</body>

</html>

Agregue la cadena de conexión de SignalR Service a la configuración de la aplicación de funciones

El último paso es establecer la cadena de conexión de SignalR Service en la configuración de la aplicación Azure Function.

  1. En Azure Portal, vaya a la instancia de SignalR que implementó anteriormente.

  2. Seleccione Claves para ver las cadenas de conexión para la instancia del servicio SignalR.

    Captura de pantalla de la página de claves del servicio Azure SignalR.

  3. Copie la cadena de conexión principal y ejecute el comando:

    func settings add AzureSignalRConnectionString "<signalr-connection-string>"
    

Ejecute localmente la aplicación de funciones de Azure

Inicie el emulador de almacenamiento de Azurite:

azurite 

Ejecute la aplicación de funciones de Azure en el entorno local:

func start

Nota

Si viera errores mostrando errores de lectura en el almacenamiento de blobs, asegúrese de que la configuración "AzureWebJobsStorage" del archivo local.settings.json esté establecida en UseDevelopmentStorage=true.

Después de que Azure Function se esté ejecutando localmente, vaya a http://localhost:7071/api/index. En la página se muestra el recuento del factor de proporcionalidad actual para el repositorio de Azure/azure-signalr de GitHub. Al activar o desactivar el factor de proporcionalidad del repositorio en GitHub, verá el recuento actualizado cada pocos segundos.

Limpieza de recursos

Si no va a seguir usando esta aplicación, siga estos pasos para eliminar todos los recursos creados en esta guía de inicio rápido a fin de que no se le apliquen cargos adicionales:

  1. En Azure Portal, seleccione Grupos de recursos en el extremo izquierdo y luego seleccione el grupo de recursos que creó. Además, puede usar el cuadro de búsqueda para buscar el grupo de recursos por su nombre.

  2. En la ventana que se abrirá, seleccione el grupo de recursos y luego haga clic en Eliminar grupo de recursos.

  3. En la nueva ventana escriba el nombre del grupo de recursos que quiere eliminar y, después, haga clic en Eliminar.

¿Tiene problemas? Consulte la guía de solución de problemas o póngase en contacto con nosotros.

Pasos siguientes

En este inicio rápido, ha compilado y ejecutado una aplicación sin servidor en tiempo real en el entorno local. En los siguientes artículos, podrá obtener más información sobre cómo establecer una comunicación bidireccional entre los clientes y Azure Function mediante SignalR Service.