Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве объясняется, как создать службу публикации в режиме реального времени для Socket.IO в режиме без сервера и разработать приложение для чата, интегрированное с функцией Azure.
Найдите полные примеры кода, используемые в этом руководстве:
Внимание
В режиме по умолчанию требуется постоянный сервер, вы не можете интегрировать Web PubSub для Socket.IO в режиме по умолчанию с функцией Azure.
Внимание
Необработанные строки подключения отображаются в этой статье в демонстрационных целях.
Строка подключения содержит сведения об авторизации, требуемые для доступа приложения к службе Azure Web PubSub. Ключ доступа в строке подключения аналогичен паролю привилегированного пользователя для службы. В рабочих средах всегда защищать ключи доступа. Используйте Azure Key Vault для безопасного управления и ротации ключей, а также для защиты вашего подключения с помощью WebPubSubServiceClient.
Старайтесь не распространять ключи доступа среди других пользователей, жестко программировать их или где-то сохранять в виде обычного текста в открытом доступе для других пользователей. Меняйте свои ключи периодически, если считаете, что они могли быть скомпрометированы.
Предварительные условия
- Учетная запись Azure с активной подпиской. Если ее нет, можно создать бесплатную учетную запись.
- Основное средство функции Azure
- Некоторые знания о библиотеке Socket.IO.
Создайте ресурс Web PubSub для Socket.IO в бессерверном режиме.
Чтобы создать web PubSub для Socket.IO, можно использовать следующую команду Azure CLI :
az webpubsub create -g <resource-group> -n <resource-name>--kind socketio --service-mode serverless --sku Premium_P1
Создание проекта функции Azure локально
Выполните действия, чтобы инициировать локальный проект функции Azure.
Следуйте шагу, чтобы установить последнюю версию основного средства функции Azure.
В окне терминала или из командной строки выполните следующую команду, чтобы создать проект в папке
SocketIOProject:func init SocketIOProject --worker-runtime javascript --model V4Эта команда создает проект JavaScript. Введите папку
SocketIOProject, чтобы выполнить следующие команды.В настоящее время пакет функций не включает привязку функции Socket.IO, поэтому необходимо вручную добавить пакет.
Чтобы исключить ссылку на пакет функций, измените файл host.json и удалите следующие строки.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Выполните команду:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Создайте функцию для согласования. Функция согласования, используемая для создания конечных точек и маркеров для доступа клиента к службе.
func new --template "Http Trigger" --name negotiateОткройте файл
src/functions/negotiate.jsи замените приведенным ниже кодом:const { app, input } = require('@azure/functions'); const socketIONegotiate = input.generic({ type: 'socketionegotiation', direction: 'in', name: 'result', hub: 'hub' }); async function negotiate(request, context) { let result = context.extraInputs.get(socketIONegotiate); return { jsonBody: result }; }; // Negotiation app.http('negotiate', { methods: ['GET', 'POST'], authLevel: 'anonymous', extraInputs: [socketIONegotiate], handler: negotiate });На этом шаге создается функция
negotiateс триггером HTTP иSocketIONegotiationвыходной привязкой, что означает, что можно использовать HTTP-вызов для активации функции и возврата результата согласования, созданногоSocketIONegotiationпривязкой.Создайте функцию для передачи сообщений.
func new --template "Http Trigger" --name messageОткройте файл
src/functions/message.jsи замените следующим кодом:const { app, output, trigger } = require('@azure/functions'); const socketio = output.generic({ type: 'socketio', hub: 'hub', }) async function chat(request, context) { context.extraOutputs.set(socketio, { actionName: 'sendToNamespace', namespace: '/', eventName: 'new message', parameters: [ context.triggerMetadata.socketId, context.triggerMetadata.message ], }); } // Trigger for new message app.generic('chat', { trigger: trigger.generic({ type: 'socketiotrigger', hub: 'hub', eventName: 'chat', parameterNames: ['message'], }), extraOutputs: [socketio], handler: chat });Эта конструкция использует
SocketIOTriggerдля срабатывания сообщения клиента Socket.IO и применяет привязкуSocketIOдля трансляции сообщений в пространстве имен.Создайте функцию, возвращающую индексную HTML-страницу для посещения.
Создайте папку
publicв разделеsrc/.Создайте HTML-файл
index.htmlсо следующим содержимым.<html> <body> <h1>Socket.IO Serverless Sample</h1> <div id="chatPage" class="chat-container"> <div class="chat-input"> <input type="text" id="chatInput" placeholder="Type your message here..."> <button onclick="sendMessage()">Send</button> </div> <div id="chatMessages" class="chat-messages"></div> </div> <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script> <script> function appendMessage(message) { const chatMessages = document.getElementById('chatMessages'); const messageElement = document.createElement('div'); messageElement.innerText = message; chatMessages.appendChild(messageElement); hatMessages.scrollTop = chatMessages.scrollHeight; } function sendMessage() { const message = document.getElementById('chatInput').value; if (message) { document.getElementById('chatInput').value = ''; socket.emit('chat', message); } } async function initializeSocket() { 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('new message', (socketId, message) => { appendMessage(`${socketId.substring(0,5)}: ${message}`); }) } initializeSocket(); </script> </body> </html>Чтобы вернуть HTML-страницу, создайте функцию и скопируйте коды.
func new --template "Http Trigger" --name indexОткройте файл
src/functions/index.jsи замените следующим кодом:const { app } = require('@azure/functions'); const fs = require('fs').promises; const path = require('path') async function index(request, context) { try { context.log(`HTTP function processed request for url "${request.url}"`); const filePath = path.join(__dirname,'../public/index.html'); const html = await fs.readFile(filePath); return { body: html, headers: { 'Content-Type': 'text/html' } }; } catch (error) { context.log(error); return { status: 500, jsonBody: error } } }; app.http('index', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: index });
Как локально запустить приложение
После подготовки кода выполните инструкции по выполнению примера.
Настройка хранилища Azure для функции Azure
Функциям Azure требуется учетная запись для хранения данных, чтобы работать, даже если они запускаются локально. Выберите один из двух следующих вариантов:
- Запустите бесплатный эмулятор Azurite.
- Используйте службу хранилища Azure. Это может привести к затратам, если вы продолжаете использовать его.
- Установка Azurite
npm install -g azurite
- Запустите эмулятор хранилища Azurite:
azurite -l azurite -d azurite\debug.log
- Убедитесь, что
AzureWebJobsStorageв local.settings.json установлено какUseDevelopmentStorage=true.
Настройка конфигурации Web PubSub для Socket.IO
- Добавьте строку подключения в функциональное приложение:
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
- Добавить настройки концентратора в Web PubSub для Socket.IO
az webpubsub hub create -n <resource name> -g <resource group> --hub-name hub --event-handler url-template="tunnel:///runtime/webhooks/socketio" user-event-pattern="*"
Строку подключения можно получить с помощью команды Azure CLI
az webpubsub key show -g <resource group> -n <resource name>
Выходные данные содержат primaryConnectionString и secondaryConnectionString, и оба доступны.
Настройка туннеля
В бессерверном режиме служба использует веб-перехватчики для активации функции. При попытке локального запуска приложения важно разрешить службе получить доступ к локальной конечной точке функции.
Самый простой способ добиться этого — использовать инструмент туннеля
Установка средства туннеля:
npm install -g @azure/web-pubsub-tunnel-toolЗапуск туннеля
awps-tunnel run --hub hub --connection "<connection string>" --upstream http://127.0.0.1:7071Это
--upstreamURL-адрес, который отображает локальная функция Azure. Порт может отличаться, и вы можете проверить выходные данные при запуске функции на следующем шаге.
Запуск примера приложения
После запуска туннеля можно локально запустить функциональное приложение:
func start
И посетите веб-страницу по адресу http://localhost:7071/api/index.
Следующие шаги
Затем можно попытаться использовать Bicep для развертывания приложения в Сети с проверкой подлинности на основе удостоверений: