如何将 Azure SignalR 服务与 Azure API 管理配合使用

Azure API 管理服务为所有环境中的 API 提供了一个混合的多云管理平台。 本文介绍如何使用 Azure API 管理和 Azure SignalR 服务向应用程序添加实时功能。

显示将 SignalR 服务与 API 管理配合使用的体系结构的示意图。

重要

本文中出现的原始连接字符串仅用于演示目的。

连接字符串包括应用程序访问 Azure SignalR 服务所需的授权信息。 连接字符串中的访问密钥类似于服务的根密码。 在生产环境中,请始终保护访问密钥。 使用 Azure 密钥保管库安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问

避免将访问密钥分发给其他用户、对其进行硬编码或将其以纯文本形式保存在其他人可以访问的任何位置。 如果你认为访问密钥可能已泄露,请轮换密钥。

创建资源

配置 API

限制

SignalR 客户端有两种类型的请求:

  • 协商请求:发送到 <APIM-URL>/client/negotiate/ 的 HTTP POST 请求
  • 连接请求:发送到 <APIM-URL>/client/ 的请求,可能是 WebSocketServerSentEventLongPolling,具体取决于 SignalR 客户端的传输类型

连接请求的类型根据 SignalR 客户端的传输类型而异。 目前,API 管理尚不支持为同一后缀使用不同类型的 API。 由于这种限制,在使用 API 管理时,SignalR 客户端不支持从 WebSocket 传输类型回退到其他传输类型。 支持从 ServerSentEvent 回退到 LongPolling。 以下部分介绍不同传输类型的详细配置。

当客户端通过 WebSocket 传输进行连接时配置 API

本部分介绍当 SignalR 客户端通过 WebSocket 传输进行连接时配置 API 管理的步骤。 当 SignalR 客户端通过 WebSocket 传输进行连接时,涉及到三种类型的请求:

  1. 用于协商的 OPTIONS 预检 HTTP 请求
  2. 用于协商的 POST HTTP 请求
  3. 用于连接的 WebSocket 请求

让我们从门户配置 API 管理。

  1. 在门户中转到 API 管理实例 APIM1 的“API”选项卡,选择“添加 API”,然后选择“HTTP”并使用以下参数创建 API
    • 显示名称:SignalR negotiate
    • Web 服务 URL:https://<your-signalr-service-url>/client/negotiate/
    • API URL 后缀:client/negotiate/
  2. 选择创建的 SignalR negotiate API,然后使用以下设置保存
    1. 在“设计”选项卡中
      1. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:negotiate preflight
        • URL:OPTIONS/
      2. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:negotiate
        • URL:POST/
    2. 切换到“设置”选项卡,并取消选中“需要订阅”以进行快速演示
  3. 选择“添加 API”,然后选择“WebSocket”并使用以下参数创建 API
    • 显示名称:SignalR connect
    • WebSocket URL:wss://<your-signalr-service-url>/client/
    • API URL 后缀:client/
  4. 选择创建的 SignalR connect API,然后使用以下设置保存
    1. 切换到“设置”选项卡,并取消选中“需要订阅”以进行快速演示

现在,API 管理已成功配置为支持具有 WebSocket 传输的 SignalR 客户端。

当客户端通过 ServerSentEventsLongPolling 传输进行连接时配置 API

本部分介绍当 SignalR 客户端通过 ServerSentEventsLongPolling 传输类型进行连接时配置 API 管理的步骤。 当 SignalR 客户端通过 ServerSentEventsLongPolling 传输进行连接时,涉及到五种类型的请求:

  1. 用于协商的 OPTIONS 预检 HTTP 请求
  2. 用于协商的 POST HTTP 请求
  3. 用于连接的 OPTIONS 预检 HTTP 请求
  4. 用于连接的 POST HTTP 请求
  5. 用于连接的 GET HTTP 请求

现在让我们从门户配置 API 管理。

  1. 在门户中转到 API 管理实例 APIM1 的“API”选项卡,选择“添加 API”,然后选择“HTTP”并使用以下参数创建 API
    • 显示名称:SignalR
    • Web 服务 URL:https://<your-signalr-service-url>/client/
    • API URL 后缀:client/
  2. 选择创建的 SignalR API,然后使用以下设置保存
    1. 在“设计”选项卡中
      1. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:negotiate preflight
        • URL:OPTIONS/negotiate
      2. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:negotiate
        • URL:POST/negotiate
      3. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:connect preflight
        • URL:OPTIONS/
      4. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:connect
        • URL:POST/
      5. 选择“添加操作”,然后使用以下参数保存
        • 显示名称:connect get
        • URL:GET/
      6. 选择新添加的“connect get”操作,然后编辑后端策略以禁用 ServerSentEvents 的缓冲,请查看此处了解更多详细信息。
        <backend>
            <forward-request buffer-response="false" />
        </backend>
        
    2. 切换到“设置”选项卡,并取消选中“需要订阅”以进行快速演示

现在,API 管理已成功配置为支持具有 ServerSentEventsLongPolling 传输的 SignalR 客户端。

运行聊天

现在,流量可以通过 API 管理到达 SignalR 服务。 让我们将此聊天应用程序用作示例。 让我们一开始在本地运行它。

本文中出现的原始连接字符串仅用于演示目的。 在生产环境中,请始终保护访问密钥。 使用 Azure Key Vault 安全地管理和轮换密钥,使用 Microsoft Entra ID 保护连接字符串,并使用 Microsoft Entra ID 授权访问

  • 首先,让我们获取 ASRS1 的连接字符串

    • 在 ASRS1 的“连接字符串”选项卡上
      • 客户端终结点:使用 APIM1 的“网关 URL”输入 URL,例如 https://apim1.azure-api.cn。 它是一个连接字符串生成器(使用反向代理时)。当你下次返回到此选项卡时,该值不会保留。输入值后,连接字符串会追加一个 ClientEndpoint 部分。
      • 复制连接字符串
  • 克隆 GitHub 存储库 https://github.com/aspnet/AzureSignalR-samples

  • 转到 samples/Chatroom 文件夹:

  • 设置复制的连接字符串并在本地运行应用程序,可以看到 ConnectionString 中有一个 ClientEndpoint 部分。

    cd samples/Chatroom
    dotnet restore
    dotnet user-secrets set Azure:SignalR:ConnectionString "<copied-connection-string-with-client-endpoint>"
    dotnet run
    
  • 配置客户端的传输类型

    打开 wwwroot 文件夹下的 index.html,找到创建 connection 时的代码,更新此代码以指定传输类型。

    例如,若要指定连接使用 server-sent-events 或长轮询,请将代码更新为:

    const connection = new signalR.HubConnectionBuilder()
      .withUrl(
        "/chat",
        signalR.HttpTransportType.ServerSentEvents |
          signalR.HttpTransportType.LongPolling
      )
      .build();
    

    若要指定连接使用 WebSocket,请将代码更新为:

    const connection = new signalR.HubConnectionBuilder()
      .withUrl("/chat", signalR.HttpTransportType.WebSockets)
      .build();
    
  • 从浏览器打开 http://localhost:5000 并使用 F12 查看网络跟踪,可以看到连接是通过 APIM1 建立的

后续步骤

现在,你已使用 Azure SignalR 成功将实时功能添加到 API 管理。 详细了解 SignalR 服务