Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento kurz vás provede publikováním dat klientům Socket.IO v režimu serverless v Pythonu pomocí tvorby aplikace NASDAQ indexu pro reálný čas, integrované s Azure Function.
Vyhledejte úplné ukázky kódu, které se používají v tomto kurzu:
Důležité
Výchozí režim vyžaduje trvalý server. Web PubSub nelze integrovat pro Socket.IO ve výchozím režimu s funkcí Azure Functions.
Požadavky
- Účet Azure s aktivním předplatným. Pokud žádné nemáte, můžete si vytvořit bezplatný účet.
- Základní nástroj azure Functions
- Znalost knihovny Socket.IO
Vytvořte Web PubSub pro zdroj Socket.IO v serverless režimu
K vytvoření služby Web PubSub pro Socket.IO můžete použít následující příkaz Azure CLI:
az webpubsub create -g <resource-group> -n <resource-name>---kind socketio --service-mode serverless --sku Premium_P1
Vytvoření projektu Azure Functions místně
Měli byste postupovat podle kroků a inicializovat místní projekt funkce Azure Functions.
Podle pokynů nainstalujte nejnovější nástroj azure Functions Core
V okně terminálu nebo z příkazového řádku spusťte následující příkaz, který vytvoří projekt ve
SocketIOProjectsložce:func init SocketIOProject --worker-runtime pythonTento příkaz vytvoří projekt funkcí založený na Pythonu. A zadáním složky
SocketIOProjectspusťte následující příkazy.V současné době sada funkcí neobsahuje vazbu funkce Socket.IO, a proto musíte balíček přidat ručně.
Pokud chcete odstranit odkaz na sadu funkcí, upravte soubor host.json a odeberte následující řádky.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Spusťte příkaz:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Nahraďte obsah
function_app.pykódy: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')Tady je vysvětlení těchto funkcí:
publish_data: Tato funkce aktualizuje NASDAQ index každou sekundu náhodnou změnou a vysílá ji připojeným klientům pomocí Socket.IO výstupního propojení.negotiate: Tato funkce odpoví na výsledek vyjednávání klientovi.index: Tato funkce vrátí statickou stránku HTML.
Pak přidejte soubor.
index.htmlVytvořte soubor index.html s obsahem:
<!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>Klíčová část v
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); }); }Nejprve vyjednává s aplikací funkcí k získání identifikátoru URI a cesty ke službě. A zaregistrujte zpětné volání pro aktualizaci indexu.
Jak aplikaci spustit místně
Jakmile je kód připravený, postupujte podle pokynů ke spuštění ukázky.
Nastavení služby Azure Storage pro funkci Azure Functions
Azure Functions vyžaduje, aby účet úložiště fungoval i v místním prostředí. Zvolte jednu z těchto dvou možností:
- Spusťte bezplatný emulátor Azurite.
- Použijte službu Azure Storage. Pokud ho budete dál používat, mohou vám být účtovány náklady.
Instalace Azurite
npm install -g azuriteSpusťte emulátor úložiště Azurite:
azurite -l azurite -d azurite\debug.logUjistěte se, že je
AzureWebJobsStoragev local.settings.json nastavena naUseDevelopmentStorage=true.
Nastavte konfiguraci Web PubSub pro Socket.IO
Přidání připojovacího řetězce do aplikace funkcí:
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
Spuštění ukázkové aplikace
Po spuštění nástroje tunelu můžete aplikaci Function App spustit místně:
func start
A navštivte webovou stránku na http://localhost:7071/api/indexadrese .
Další kroky
Dále se můžete pokusit pomocí Bicep nasadit aplikaci online s ověřováním na základě identity: