Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra come pubblicare dati in Socket.IO client in modalità serverless in Python creando un'applicazione di indice NASDAQ in tempo reale integrata con funzioni di Azure.
Trovare esempi di codice completi usati in questa esercitazione:
Importante
La modalità predefinita richiede un server persistente, non è possibile integrare Web PubSub per Socket.IO in modalità predefinita con Funzioni di Azure.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Se non ne hai uno, puoi creare un account gratuito.
- Strumento di base di Funzioni di Azure
- Una certa familiarità con la libreria di Socket.IO.
Creare un Web PubSub per la risorsa Socket.IO in modalità serverless
Per creare un web pubSub per Socket.IO, è possibile usare il comando seguente dell'interfaccia della riga di comando di Azure:
az webpubsub create -g <resource-group> -n <resource-name>---kind socketio --service-mode serverless --sku Premium_P1
Creare un progetto di Funzioni di Azure in locale
È necessario seguire la procedura per avviare un progetto di Funzioni di Azure locale.
Seguire la procedura per installare lo strumento di base di Funzioni di Azure più recente
Nella finestra del terminale o da un prompt dei comandi eseguire il comando seguente per creare un progetto nella cartella
SocketIOProject:func init SocketIOProject --worker-runtime pythonQuesto comando crea un progetto funzione basato su Python. Immettere la cartella
SocketIOProjectper eseguire i comandi seguenti.Attualmente, il pacchetto di funzioni non include il binding di funzioni Socket.IO, quindi è necessario aggiungere manualmente il pacchetto.
Per eliminare il riferimento al pacchetto di funzioni, modificare il file host.json e rimuovere le righe seguenti.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Eseguire il comando:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Sostituire il contenuto in
function_app.pycon i codici:import random import azure.functions as func from azure.functions.decorators.core import DataType from azure.functions import Context import json app = func.FunctionApp() current_index= 14000 @app.timer_trigger(schedule="* * * * * *", arg_name="myTimer", run_on_startup=False, use_monitor=False) @app.generic_output_binding("sio", type="socketio", data_type=DataType.STRING, hub="hub") def publish_data(myTimer: func.TimerRequest, sio: func.Out[str]) -> None: change = round(random.uniform(-10, 10), 2) global current_index current_index = current_index + change sio.set(json.dumps({ 'actionName': 'sendToNamespace', 'namespace': '/', 'eventName': 'update', 'parameters': [ current_index ] })) @app.function_name(name="negotiate") @app.route(auth_level=func.AuthLevel.ANONYMOUS) @app.generic_input_binding("negotiationResult", type="socketionegotiation", hub="hub") def negotiate(req: func.HttpRequest, negotiationResult) -> func.HttpResponse: return func.HttpResponse(negotiationResult) @app.function_name(name="index") @app.route(auth_level=func.AuthLevel.ANONYMOUS) def index(req: func.HttpRequest) -> func.HttpResponse: path = './index.html' with open(path, 'rb') as f: return func.HttpResponse(f.read(), mimetype='text/html')Ecco la spiegazione di queste funzioni:
publish_data: questa funzione aggiorna l'indice NASDAQ ogni secondo con una modifica casuale e lo trasmette ai client connessi con Socket.IO binding di output.negotiate: Questa funzione restituisce un risultato della negoziazione al cliente.index: questa funzione restituisce una pagina HTML statica.
Aggiungere quindi un
index.htmlfileCreare il file index.html con il contenuto:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Nasdaq Index</title> <style> /* Reset some default styles */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #f5f7fa, #c3cfe2); height: 100vh; display: flex; justify-content: center; align-items: center; } .container { background-color: white; padding: 40px; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); text-align: center; max-width: 300px; width: 100%; } .nasdaq-title { font-size: 2em; color: #003087; margin-bottom: 20px; } .index-value { font-size: 3em; color: #16a34a; margin-bottom: 30px; transition: color 0.3s ease; } .update-button { padding: 10px 20px; font-size: 1em; color: white; background-color: #003087; border: none; border-radius: 6px; cursor: pointer; transition: background-color 0.3s ease; } .update-button:hover { background-color: #002070; } </style> </head> <body> <div class="container"> <div class="nasdaq-title">STOCK INDEX</div> <div id="nasdaqIndex" class="index-value">14,000.00</div> </div> <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script> <script> function updateIndexCore(newIndex) { newIndex = parseFloat(newIndex); currentIndex = parseFloat(document.getElementById('nasdaqIndex').innerText.replace(/,/g, '')) change = newIndex - currentIndex; // Update the index value in the DOM document.getElementById('nasdaqIndex').innerText = newIndex.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}); // Optionally, change the color based on increase or decrease const indexElement = document.getElementById('nasdaqIndex'); if (change > 0) { indexElement.style.color = '#16a34a'; // Green for increase } else if (change < 0) { indexElement.style.color = '#dc2626'; // Red for decrease } else { indexElement.style.color = '#16a34a'; // Neutral color } } async function init() { const negotiateResponse = await fetch(`/api/negotiate`); if (!negotiateResponse.ok) { console.log("Failed to negotiate, status code =", negotiateResponse.status); return; } const negotiateJson = await negotiateResponse.json(); socket = io(negotiateJson.endpoint, { path: negotiateJson.path, query: { access_token: negotiateJson.token} }); socket.on('update', (index) => { updateIndexCore(index); }); } init(); </script> </body> </html>Parte chiave in
index.html:async function init() { const negotiateResponse = await fetch(`/api/negotiate`); if (!negotiateResponse.ok) { console.log("Failed to negotiate, status code =", negotiateResponse.status); return; } const negotiateJson = await negotiateResponse.json(); socket = io(negotiateJson.endpoint, { path: negotiateJson.path, query: { access_token: negotiateJson.token} }); socket.on('update', (index) => { updateIndexCore(index); }); }Prima di tutto negozia con l'app per le funzioni per ottenere l'URI e il percorso al servizio. Registrare un callback per aggiornare l'indice.
Come eseguire l'app in locale
Dopo aver preparato il codice, seguire le istruzioni per eseguire l'esempio.
Configurare Archiviazione di Azure per Funzioni di Azure
Funzioni di Azure richiede che un account di archiviazione possa essere eseguito anche in locale. Scegliere una delle due opzioni seguenti:
- Eseguire l'emulatore Azurite gratuito.
- Usare il servizio Archiviazione di Azure. Ciò può comportare costi se si continua a usarlo.
Installare Azurite
npm install -g azuriteAvviare l'emulatore di archiviazione Azurite:
azurite -l azurite -d azurite\debug.logAssicurarsi che
AzureWebJobsStoragein local.settings.json sia impostato suUseDevelopmentStorage=true.
Impostare la configurazione di Web PubSub per Socket.IO
Aggiungere una stringa di connessione all'app per le funzioni:
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
Eseguire un'app di esempio
Dopo l'esecuzione dello strumento tunnel, è possibile eseguire l'app per le funzioni in locale:
func start
Visitare la pagina Web all'indirizzo http://localhost:7071/api/index.
Passaggi successivi
Successivamente, è possibile provare a usare Bicep per distribuire l'app online con l'autenticazione basata sull'identità: