发布于 2026-01-06 1 阅读
0

使用 Azure SignalR 服务构建实时无服务器应用程序

使用 Azure SignalR 服务构建实时无服务器应用程序

今天,微软宣布Azure SignalR 服务绑定正式面向 Azure Functions 推出。这些绑定使 Azure Functions 能够与 SignalR 服务无缝集成,并通过 WebSocket 大规模广播实时消息。

我们将探讨如何使用 HTML 和 JavaScript 构建一个基于浏览器的协作绘图应用程序。多人可以在各自的浏览器中打开该应用程序,并在画布上进行绘制。所有更改都会使用 Azure Functions 和 SignalR 服务实时同步。

Azure Functions 近期也正式推出了对 Java 语言的支持。本文中,我们将使用 Java 编写函数,但 SignalR 服务绑定也适用于 Azure Functions 支持的其他语言。您可以访问GitHub 代码库查看Java、C# 和 JavaScript 的源代码。

概述

该应用程序由三个主要组件构成:绘图画布、Azure 函数应用程序和 Azure SignalR 服务。

建筑学

  1. Canvas 是一个简单的 JavaScript 应用,运行在浏览器中。应用启动时,它会从名为“negotiate”的 Azure 函数中检索 SignalR 服务连接终结点和访问令牌。

  2. 该应用连接到 SignalR 服务并建立实时通道。通常情况下,这是一个 WebSocket 连接,但如果 WebSocket 不可用,SignalR 会自动回退到其他传输方式。

  3. 当在画布上绘制线条时,该应用程序会将一系列笔画发送到名为“draw”的 Azure 函数。

  4. 绘图 Azure 函数使用 SignalR 服务将一系列笔画广播到所有已连接的客户端。

创建 Azure SignalR 服务实例

Azure SignalR 服务是一个完全托管的实时消息平台,我们的应用程序将使用它来广播消息。我们可以在 Azure 门户中创建一个免费的SignalR 服务实例,也可以运行以下 Azure CLI 命令。

az signalr create -n $SIGNALR_NAME -g $GROUP_NAME --sku Free_DS2 -l westus
Enter fullscreen mode Exit fullscreen mode

实例创建完成后,我们需要获取函数应用将使用的连接字符串。

az signalr key list -n $SIGNALR_NAME -g $GROUP_NAME
Enter fullscreen mode Exit fullscreen mode

构建 Azure 函数应用

Azure 函数应用包含两个关键函数。第一个negotiate函数返回 SignalR 服务连接信息。第二个函数draw会在任何画布上绘制线条时被调用;它会将这些线条广播到其他画布。

如果您之前没有使用过 Azure Functions,请查看他们的快速入门指南

协商功能

此 HTTP 触发函数使用SignalRConnectionInfoInput绑定来生成客户端的访问令牌和端点信息。绑定使用连接字符串生成这些信息。

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
    @HttpTrigger(
      name = "req",
      methods = { HttpMethod.POST },
      authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
    @SignalRConnectionInfoInput(
      name = "connectionInfo",
      hubName = "serverlessdraw") SignalRConnectionInfo connectionInfo) {
  return connectionInfo;
}
Enter fullscreen mode Exit fullscreen mode

绘制函数

HTTPdraw触发函数使用SignalROutput绑定将绘制在画布上的笔画广播到当前连接到 SignalR 服务的所有画布。

它只是将 HTTP 请求正文的内容转发给 SignalR 服务。

@FunctionName("draw")
public void draw(
    @HttpTrigger(
      name = "req",
      methods = { HttpMethod.POST },
      authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<StrokeCollection> req,
    @SignalROutput(
      name = "signalRMessage",
      hubName = "serverlessdraw") OutputBinding<SignalRMessage> signalRMessage) {

  StrokeCollection strokeCollection = req.getBody();
  SignalRMessage msg = new SignalRMessage("newStrokes", strokeCollection);
  signalRMessage.setValue(msg);
}
Enter fullscreen mode Exit fullscreen mode

创建绘图画布

Canvas 是一个出乎意料地简单的基于浏览器的 JavaScript 应用,它使用 HTML Canvas。你可以在我的 Twitch 直播中观看我构建它的第一个版本。

SignalR 服务连接

Canvas 应用启动后,我们首先要做的就是连接到 SignalR 服务。我们可以使用 CDN 来引用 SignalR JavaScript 客户端。

<script src="https://cdn.jsdelivr.net/npm/@aspnet/signalr@1.1.2/dist/browser/signalr.js"></script>
Enter fullscreen mode Exit fullscreen mode

然后我们可以使用客户端创建与 SignalR 服务的连接。按照惯例,SignalR 客户端会/negotiate在 URL 末尾添加一个参数来发现连接协商端点,因此在初始化函数时,我们会将这部分从函数的 URL 中省略HubConnectionBuilder

var connection = new signalR.HubConnectionBuilder()
  .withUrl(`${apiBaseUrl}/api`) // function URL minus /negotiate
  .build()

// set up event listeners
connection.on('newStrokes', drawStrokes)
connection.on('clearCanvas', clearCanvas)

connection.start()
  .then(() => console.log('connected'))
Enter fullscreen mode Exit fullscreen mode

在配置连接并启动连接的过程中,我们设置了几个事件监听器。当 SignalR 服务收到与这些名称匹配的事件时,就会调用相应的事件处理程序。以下是该clearCanvas函数的代码:

function clearCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}
Enter fullscreen mode Exit fullscreen mode

绘画画布

主画布(正如你所料)就是一个单独的<canvas>标签:

<canvas id="draw-canvas" height="500" width="800"></canvas>
Enter fullscreen mode Exit fullscreen mode

主要的 JavaScript 函数名为 ` mouseMovedrawStroke`。每次绘制笔画时都会调用它。我们确定线条的起点和终点,并将其绘制在画布上。然后,我们将笔画添加到数组中,以便将多个笔画收集起来并批量发送。

function mouseMove(ev) {

  // 🌟 math happens here

  drawStroke(start, end, colorButton.value)
  unsentStrokes.push({
    start: start,
    end: end,
    color: colorButton.value
  })
}
Enter fullscreen mode Exit fullscreen mode

我们大约每隔 250 毫秒将一批笔画发送到我们的drawAzure 函数。

setInterval(function () {
  if (unsentStrokes.length) {
    axios.post(`${apiBaseUrl}/api/draw`, {
      sender: clientId,
      strokes: unsentStrokes
    })
    unsentStrokes = []
  }
}, 250)
Enter fullscreen mode Exit fullscreen mode

绘制函数将使用 SignalR 服务newStrokes在应用程序的每个运行实例中触发事件。这将调用一个名为 draw 的函数drawStrokes来绘制笔画。

成品长这样:

无服务器绘图应用程序

请查看GitHub 仓库,获取 Java、JavaScript 和 C# 编写的函数应用程序的源代码。

资源

文章来源:https://dev.to/azure/build-real-time-serverless-apps-with-azure-signalr-service-1fin