Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym samouczku przedstawiono sposób publikowania danych na Socket.IO klientach w trybie bezserwerowym w języku Python przez utworzenie aplikacji indeksu NASDAQ w czasie rzeczywistym zintegrowanej z funkcją platformy Azure.
Znajdź pełne przykłady kodu używane w tym samouczku:
Ważne
Tryb domyślny wymaga trwałego serwera. Nie można zintegrować usługi Web PubSub dla Socket.IO w trybie domyślnym z funkcją platformy Azure.
Wymagania wstępne
- Konto Azure z aktywną subskrypcją. Jeśli go nie masz, możesz utworzyć bezpłatne konto.
- Podstawowe narzędzie funkcji platformy Azure
- Znajomość biblioteki Socket.IO.
Tworzenie usługi Web PubSub dla zasobu Socket.IO w trybie bezserwerowym
Aby utworzyć usługę Web PubSub dla Socket.IO, możesz użyć następującego polecenia interfejsu wiersza polecenia platformy Azure :
az webpubsub create -g <resource-group> -n <resource-name>---kind socketio --service-mode serverless --sku Premium_P1
Lokalne tworzenie projektu funkcji platformy Azure
Należy wykonać kroki, aby zainicjować lokalny projekt funkcji platformy Azure.
Wykonaj kroki, aby zainstalować najnowsze narzędzie podstawowe funkcji platformy Azure
W oknie terminalu lub w wierszu polecenia uruchom następujące polecenie, aby utworzyć projekt w folderze
SocketIOProject:func init SocketIOProject --worker-runtime pythonTo polecenie tworzy projekt funkcji oparty na języku Python. Przejdź do folderu
SocketIOProject, aby uruchomić następujące polecenia.Obecnie pakiet funkcji nie zawiera Socket.IO powiązania funkcji, dlatego należy ręcznie dodać pakiet.
Aby wyeliminować odwołanie do pakietu funkcji, zmodyfikuj plik host.json i usuń następujące wiersze.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Uruchom polecenie:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Zastąp zawartość w
function_app.pypliku kodami: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')Oto wyjaśnienie tych funkcji:
publish_data: Ta funkcja aktualizuje indeks NASDAQ co sekundę za pomocą losowej zmiany i emituje go do połączonych klientów z wyjściowym bindigiem Socket.IO.negotiate: Ta funkcja odpowiada na wynik negocjacji dla klienta.index: Ta funkcja zwraca statyczną stronę HTML.
Następnie dodaj
index.htmlplikUtwórz plik index.html z zawartością:
<!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>Kluczowa część w
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); }); }Najpierw negocjuje z aplikacją Function App, aby uzyskać URI i ścieżkę do usługi. Zarejestruj wywołanie zwrotne w celu zaktualizowania indeksu.
Jak uruchomić aplikację lokalnie
Po przygotowaniu kodu wykonaj instrukcje uruchamiania przykładu.
Konfigurowanie usługi Azure Storage dla funkcji platformy Azure
Usługa Azure Functions wymaga konta magazynu do działania, nawet gdy jest uruchomiona lokalnie. Wybierz jedną z dwóch następujących opcji:
- Uruchom bezpłatny emulator Azurite.
- Użyj usługi Azure Storage. Może to wiązać się z kosztami, jeśli będzie on nadal używany.
Instalowanie Azurite
npm install -g azuriteUruchom emulator magazynu Azurite:
azurite -l azurite -d azurite\debug.logUpewnij się, że
AzureWebJobsStoragew local.settings.json ustawiono wartośćUseDevelopmentStorage=true.
Ustawienie konfiguracji usługi Web PubSub dla Socket.IO
Dodaj ciąg połączenia do aplikacji Function.
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
Uruchamianie przykładowej aplikacji
Po uruchomieniu narzędzia tunelu możesz uruchomić aplikację funkcji lokalnie:
func start
Odwiedź stronę internetową pod adresem http://localhost:7071/api/index.
Dalsze kroki
Następnie możesz spróbować użyć aplikacji Bicep do wdrożenia aplikacji w trybie online przy użyciu uwierzytelniania opartego na tożsamościach: