Azure Functions development and configuration with Azure SignalR Service (Разработка и настройка функций Azure с помощью Службы Azure SignalR)

Функции Azure приложения могут использовать привязки Служба Azure SignalR для добавления возможностей в режиме реального времени. Клиентские приложения используют клиентские пакеты SDK, доступные на нескольких языках, для подключения к Службе Azure SignalR и получения сообщений в режиме реального времени.

В этой статье описываются основные понятия разработки и настройки приложения-функции Azure с интеграцией со Службой SignalR.

Конфигурация Службы SignalR

Служба Azure SignalR можно настроить в разных режимах. При использовании с платформой Функции Azure служба должна быть настроена в Бессерверном режиме.

На портале Azure откройте страницу Параметры для ресурса Службы SignalR. Установите Режим службы — Бессерверный.

Режим Службы SignalR

Разработка функций Azure

Для бессерверного приложения в режиме реального времени, созданного с Функции Azure и Служба Azure SignalR, требуется по крайней мере два Функции Azure:

  • Функцияnegotiate, вызываемая клиентом для получения допустимого Служба SignalR маркера доступа и URL-адреса конечной точки.
  • Одна или несколько функций, обрабатывающих сообщения, отправляемые из Служба SignalR клиентам.

Функция согласования

Клиентскому приложению требуется допустимый токен доступа для подключения к Службе Azure SignalR. Маркер доступа может быть анонимным или прошедшим проверку подлинности в идентификаторе пользователя. Бессерверным Служба SignalR приложениям требуется конечная точка HTTP с именем negotiate для получения маркера и других сведений о подключении, например URL-адрес конечной точки Служба SignalR.

Используйте функцию Azure с триггером HTTP и SignalRConnectionInfo входную привязку для создания объекта сведений о подключении. Функция должна иметь маршрут HTTP, который заканчивается на /negotiate.

При использовании модели на основе классов в C#не требуется SignalRConnectionInfo входная привязка и можно гораздо проще добавлять пользовательские утверждения. Дополнительные сведения см. в разделе "Согласование" в модели на основе классов.

Дополнительные сведения о функции см. в negotiate Функции Azure разработке.

Чтобы узнать, как создать маркер, прошедший проверку подлинности, см. статью "Использование проверки подлинности Служба приложений".

Обработка сообщений от Службы SignalR

Используйте привязку SignalRTrigger для обработки сообщений, отправленных из Служба SignalR. Вы можете получать уведомления, когда клиенты отправляют сообщения или когда клиенты подключаются и отключаются.

Дополнительные сведения см. в справочнике по привязке триггеров Служба SignalR.

Кроме того, необходимо настроить конечную точку функции как вышестоящую конечную точку, чтобы служба активировала функцию при наличии сообщения от клиента. Дополнительные сведения о настройке конечных точек вышестоящего потока см. в разделе "Конечные точки вышестоящего потока".

Примечание.

Служба SignalR не поддерживает StreamInvocation сообщение от клиента в бессерверном режиме.

Отправка сообщений и управление членством в группах

Используйте выходную привязку SignalR для отправки сообщений клиентам, подключенным к Служба Azure SignalR. Вы можете передавать сообщения всем клиентам или отправлять их в подмножество клиентов. Например, только отправлять сообщения клиентам, прошедшим проверку подлинности с определенным идентификатором пользователя или только в определенную группу.

Пользователи могут быть добавлены в одну или несколько групп. Вы также можете использовать выходную привязку SignalR для добавления или удаления пользователей в группы или из нее.

Дополнительные сведения см. в справочнике по выходной привязке.SignalR

Концентраторы SignalR

SignalR имеет концепцию концентраторов. Каждое клиентское подключение и каждое сообщение, отправленное из Функций Azure, ограничены конкретным концентратором. Концентраторы можно использовать как способ разделения подключений и сообщений на логические пространства имен.

Модель на основе классов

Модель на основе классов выделена для C#.

Модель на основе классов обеспечивает более эффективное программирование, которое может заменить входные и выходные привязки SignalR следующими функциями:

  • Более гибкие переговоры, отправка сообщений и управление возможностями групп.
  • Поддерживаются дополнительные функции управления, включая закрытие подключений, проверку наличия подключения, пользователя или группы.
  • Строго типизированный концентратор
  • Единое имя концентратора и строка подключения параметр в одном месте.

В следующем коде показано, как записывать привязки SignalR в модель на основе классов:

Сначала определите центр, производный от класса ServerlessHub:

[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub
{
    private const string HubName = nameof(Functions); // Used by SignalR trigger only

    public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
    {
    }

    [Function("negotiate")]
    public async Task<HttpResponseData> Negotiate([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
    {
        var negotiateResponse = await NegotiateAsync(new() { UserId = req.Headers.GetValues("userId").FirstOrDefault() });
        var response = req.CreateResponse();
        response.WriteBytes(negotiateResponse.ToArray());
        return response;
    }

    [Function("Broadcast")]
    public Task Broadcast(
    [SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
    {
        return Clients.All.SendAsync("newMessage", new NewMessage(invocationContext, message));
    }

    [Function("JoinGroup")]
    public Task JoinGroup([SignalRTrigger(HubName, "messages", "JoinGroup", "connectionId", "groupName")] SignalRInvocationContext invocationContext, string connectionId, string groupName)
    {
        return Groups.AddToGroupAsync(connectionId, groupName);
    }
}

В файле Program.cs зарегистрируйте бессерверный концентратор:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(b => b.Services
        .AddServerlessHub<Functions>())
    .Build();

Взаимодействие с согласованием в модели на основе классов

Вместо использования входной привязки SignalR переговоры [SignalRConnectionInfoInput]в модели на основе классов могут быть более гибкими. Базовый класс ServerlessHub имеет метод NegotiateAsync, который позволяет пользователям настраивать параметры согласования, такие как userId, claimsи т. д.

Task<BinaryData> NegotiateAsync(NegotiationOptions? options = null)

Отправка сообщений и управление ими в модели на основе классов

Вы можете отправлять сообщения, управлять группами или управлять клиентами, доступом к членам, предоставляемым базовым классом ServerlessHub.

  • ServerlessHub.Clients для отправки сообщений клиентам.
  • ServerlessHub.Groups для управления подключениями с группами, например добавление подключений к группам, удаление подключений из групп.
  • ServerlessHub.UserGroups для управления пользователями с группами, например добавление пользователей в группы, удаление пользователей из групп.
  • ServerlessHub.ClientManager для проверки существования подключений, закрытия подключений и т. д.

Строго типизированный концентратор

Строго типизированный концентратор позволяет использовать строго типизированные методы при отправке сообщений клиентам. Чтобы использовать строго типизированный концентратор в модели на основе классов, извлеките клиентские методы в интерфейс Tи сделайте класс концентратора производным от ServerlessHub<T>.

Следующий код — это пример интерфейса для клиентских методов.

public interface IChatClient
{
    Task newMessage(NewMessage message);
}

Затем можно использовать строго типизированные методы следующим образом:

[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub<IChatClient>
{
    private const string HubName = nameof(Functions);  // Used by SignalR trigger only

    public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
    {
    }

    [Function("Broadcast")]
    public Task Broadcast(
    [SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
    {
        return Clients.All.newMessage(new NewMessage(invocationContext, message));
    }
}

Примечание.

Полный пример проекта можно получить на сайте GitHub.

Единое имя концентратора и параметр строка подключения в одном месте

  • Имя класса бессерверного концентратора автоматически используется в качестве HubName.
  • Возможно, вы заметили, что атрибут, используемый SignalRConnection в бессерверных классах концентраторов, как показано ниже.
    [SignalRConnection("AzureSignalRConnectionString")]
    public class Functions : ServerlessHub<IChatClient>
    
    Он позволяет настроить расположение строка подключения для бессерверного концентратора. Если он отсутствует, используется значение AzureSignalRConnectionString по умолчанию.

Внимание

Триггеры SignalR и бессерверные концентраторы независимы. Таким образом, имя класса бессерверного концентратора и SignalRConnection атрибута не изменяет параметры триггеров SignalR, даже если вы используете триггеры SignalR внутри бессерверного концентратора.

Разработка клиентских приложений

Клиентские приложения SignalR могут использовать клиентский пакет SDK SignalR на одном из нескольких языков, чтобы легко подключаться к Служба Azure SignalR и получать сообщения.

Конфигурация подключения клиента

Чтобы подключиться к службе SignalR, клиент должен завершить успешное согласование подключения, которое состоит из следующих действий.

  1. Выполните запрос к конечной точке negotiate HTTP, описанной выше, чтобы получить допустимые сведения о подключении
  2. Подключение к Служба SignalR с помощью URL-адреса конечной точки службы и маркера доступа, полученного из конечной negotiate точки.

Клиентские пакеты SDK SignalR уже включают логику, необходимую для выполнения рукопожатия с согласованием. Передайте URL-адрес конечной точки переговоров, минус negotiate сегмент, в пакет SDK HubConnectionBuilder. Ниже приведен пример в JavaScript:

const connection = new signalR.HubConnectionBuilder()
  .withUrl("https://my-signalr-function-app.azurewebsites.net/api")
  .build();

Обычно пакет SDK автоматически присоединяет /negotiate к URL-адресу и использует его для начала согласования.

Примечание.

Если вы используете пакет SDK для JavaScript/TypeScript в браузере, необходимо включить общий доступ к ресурсам независимо от источника (CORS) в приложении-функции Azure.

Дополнительные сведения об использовании клиентского пакета SDK SignalR см. в документации по языку:

Отправка сообщений от клиента к службе

Если вы настроили вышестоящий поток для ресурса SignalR, вы можете отправлять сообщения от клиента в Функции Azure с помощью любого клиента SignalR. Ниже приведен пример в JavaScript:

connection.send("method1", "arg1", "arg2");

Конфигурация платформы Функции Azure

Приложения-функции Azure, интегрированные со Службой Azure SignalR, можно развернуть как любое типичное приложение-функцию Azure с помощью таких методик, как: непрерывное развертывание, развертывание из ZIP-файла и запуск из пакета.

Однако существует несколько особых способов для приложений, использующих привязки Службы SignalR. Если клиент выполняется в браузере, необходимо включить CORS. Если приложению требуется проверка подлинности, можно интегрировать конечную точку переговоров с Служба приложений аутентификации.

Включение CORS

Клиент JavaScript/TypeScript отправляет HTTP-запрос в функцию согласования, чтобы инициировать согласование соединения. Если клиентское приложение размещено в другом домене, отличном от приложения-функции Azure, необходимо включить совместное использование ресурсов между источниками (CORS) в приложении-функции или браузер заблокирует запросы.

Localhost

При запуске приложения-функции на локальном компьютере можно добавить раздел Host в local.settings.json, чтобы включить CORS. В разделе Host добавьте два свойства:

  • CORS — введите базовый URL-адрес, который является источником клиентского приложения.
  • CORSCredentials — установите значение true, чтобы разрешить запросы "withCredentials".

Пример:

{
  "IsEncrypted": false,
  "Values": {
    // values
  },
  "Host": {
    "CORS": "http://localhost:8080",
    "CORSCredentials": true
  }
}

CORS к Функциям Azure из облака

Чтобы включить CORS в приложении на платформе Функции Azure, перейдите на экран конфигурации CORS на вкладке Возможности приложения-функции на портале Azure.

Примечание.

Конфигурация CORS пока недоступна для плана Потребления Linux в Функциях Azure. Используйте Управление API Azure, чтобы включить CORS.

CORS с помощью access-Control-Allow-Credentials необходимо включить, чтобы клиент SignalR вызывал функцию согласования. Чтобы включить его, установите флажок.

В разделе Разрешенные источники добавьте запись с базовым URL-адресом источника вашего приложения.

Конфигурация CORS

Управление API Azure из облака

Управление API Azure предоставляет шлюз API, который добавляет возможности к существующим серверным службам. С ее помощью можно добавить CORS к вашему приложению-функции. Служба поставляется на уровне потребления с оплатой за действия и бесплатным ежемесячным лимитом.

Сведения о том, как импортировать приложение-функцию Azure, см. в документации по Управлению API. После импорта можно добавить политику входящего трафика, чтобы включить CORS с поддержкой Access-Control-Allow-Credentials.

<cors allow-credentials="true">
  <allowed-origins>
    <origin>https://azure-samples.github.io</origin>
  </allowed-origins>
  <allowed-methods>
    <method>GET</method>
    <method>POST</method>
  </allowed-methods>
  <allowed-headers>
    <header>*</header>
  </allowed-headers>
  <expose-headers>
    <header>*</header>
  </expose-headers>
</cors>

Настройте клиенты SignalR для использования URL-адреса службы Управления API.

Использование проверки подлинности Службы приложений Azure

Функции Azure имеет встроенную проверку подлинности, поддерживая популярные поставщики, такие как Facebook, X, Учетная запись Майкрософт, Google и Идентификатор Microsoft Entra. Эту функцию можно интегрировать с SignalRConnectionInfo привязкой для создания подключений к Служба Azure SignalR, прошедших проверку подлинности в идентификаторе пользователя. Приложение может отправлять сообщения с помощью выходной привязки, предназначенной SignalR для этого идентификатора пользователя.

На портале Azure на вкладке Возможности приложения-функции откройте окно параметров Проверка подлинности и авторизация. Чтобы настроить проверку подлинности с помощью выбранного поставщика удостоверений, следуйте инструкциям в документации по проверке подлинности Службы приложений Azure.

После настройки прошедшие проверку подлинности HTTP-запросы включают x-ms-client-principal-name и x-ms-client-principal-id заголовки, содержащие имя пользователя и идентификатор пользователя, прошедшие проверку подлинности, соответственно.

Эти заголовки можно использовать в SignalRConnectionInfo конфигурации привязки для создания прошедших проверку подлинности подключений. Ниже приведен пример функции согласования C#, которая использует x-ms-client-principal-id заголовок.

[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
    [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
    [SignalRConnectionInfo
        (HubName = "chat", UserId = "{headers.x-ms-client-principal-id}")]
        SignalRConnectionInfo connectionInfo)
{
    // connectionInfo contains an access key token with a name identifier claim set to the authenticated user
    return connectionInfo;
}

Затем можно отправлять сообщения этому пользователю, задав свойство UserId сообщения SignalR.

[FunctionName("SendMessage")]
public static Task SendMessage(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")]object message,
    [SignalR(HubName = "chat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
    return signalRMessages.AddAsync(
        new SignalRMessage
        {
            // the message will only be sent to these user IDs
            UserId = "userId1",
            Target = "newMessage",
            Arguments = new [] { message }
        });
}

Сведения о других языках см. в справочнике по привязкам Службы Azure SignalR для Функций Azure.

Следующие шаги

В этой статье вы узнаете, как разрабатывать и настраивать бессерверные приложения Служба SignalR с помощью Функции Azure. Попробуйте создать приложение самостоятельно с помощью одного из быстрых запусков или руководств на странице обзора Службы SignalR.