自定义 Azure Fluid Relay 服务


虽然你可能更喜欢使用我们的免费托管服务,但在某些情况下,为 Live Share 应用使用自己的 Azure Fluid Relay 服务会很有帮助。

先决条件

  1. 生成会议侧面板和舞台应用会议扩展,如 骰子滚筒教程中所示。
  2. 更新应用清单以包含 所有必要的权限
  3. 预配 Azure Fluid Relay 服务,如 本教程中所述。

连接到 Azure Fluid Relay 服务

调用初始化 LiveShareClient时,可以定义自己的 AzureConnectionConfig。 Live Share 会将你创建的容器与会议相关联,但你需要实现 接口 ITokenProvider 来为容器签名令牌。 此示例介绍 Azure 的 AzureFunctionTokenProvider,它使用 Azure 云函数从服务器请求访问令牌。

import { LiveShareClient, LivePresence } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";
import { AzureFunctionTokenProvider } from "@fluidframework/azure-client";

// Define a custom connection for your app
const options = {
  connection: {
    tenantId: "MY_TENANT_ID",
    tokenProvider: new AzureFunctionTokenProvider(
      "MY_SERVICE_ENDPOINT_URL" + "/api/GetAzureToken",
      { userId: "userId", userName: "Test User" }
    ),
    endpoint: "MY_SERVICE_ENDPOINT_URL",
    type: "remote",
  },
};
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host, options);
const schema = {
  initialObjects: {
    presence: LivePresence,
    ticTacToePositions: SharedMap,
  },
};
const { container } = await liveShare.joinContainer(schema);

// ... ready to start app sync logic

为何使用自定义 Azure Fluid Relay 服务?

在以下情况下,请考虑使用自定义 AFR 服务连接:

  • 要求在会议生存期之后在 Fluid 容器中存储数据。
  • 通过需要自定义安全策略的服务传输敏感数据。
  • 通过 Fluid Framework 为 Teams 外部的应用程序开发功能。

为什么要将 Live Share 与自定义服务配合使用?

Azure Fluid Relay 旨在与任何基于 Web 的应用程序配合使用,这意味着它适用于 Microsoft Teams 或不使用 Microsoft Teams。 这引发了一个重要问题:如果我生成自己的 Azure Fluid Relay 服务,是否仍需要 Live Share?

Live Share 具有有利于增强应用中其他功能的常见会议方案的功能,包括:

容器映射

LiveShareClient中的 @microsoft/live-share 负责将唯一的会议标识符映射到 Fluid 容器,以确保所有会议参与者都加入同一容器。 在此过程中,客户端尝试连接到 containerId 映射到已存在的会议。 如果不存在, AzureClient 则用于使用 创建 AzureConnectionConfig 容器,然后将 中继 containerId 到其他会议参与者。

如果你的应用已具有创建 Fluid 容器并将其共享给其他成员的机制,例如将 插入 containerId 到共享到会议阶段的 URL 中,则你的应用可能不需要这样做。

实时对象和角色验证

Live Share 的实时数据结构(如 LivePresenceLiveStateLiveEvent )专为会议中的协作而定制,因此在 Microsoft Teams 外部使用的 Fluid 容器中不受支持。 角色验证等功能可帮助应用符合用户的期望。

注意

与传统的 Fluid 数据结构相比,实时对象还具有更快的消息延迟,这是一个额外的优势。

有关详细信息,请参阅 核心功能 页。

使用不带 LiveShareClient 的 Live Share

即使使用 不希望将 类用于自定义 Azure Fluid Relay 服务, LiveShareClient 你仍然可以使用 Live Share。 如果要控制何时创建容器或如何与会议参与者共享容器,这将很有帮助。

下面是如何在应用程序中执行此操作的示例:

import {
  LiveShareClient,
  LivePresence,
  getLiveShareContainerSchemaProxy,
} from "@microsoft/live-share";
import { SharedMap } from "fluid-framework";
import {
  AzureFunctionTokenProvider,
  AzureClient,
} from "@fluidframework/azure-client";
import { LiveShareHost } from "@microsoft/teams-js";

// Define a custom connection for your app
const options = {
  connection: {
    tenantId: "MY_TENANT_ID",
    tokenProvider: new AzureFunctionTokenProvider(
      "MY_SERVICE_ENDPOINT_URL" + "/api/GetAzureToken",
      { userId: "userId", userName: "Test User" }
    ),
    endpoint: "MY_SERVICE_ENDPOINT_URL",
    type: "remote",
  },
};
// Initialize your AzureClient instance
const client = new AzureClient(options);
// Define your Fluid schema
const schema = {
  initialObjects: {
    presence: LivePresence,
    ticTacToePositions: SharedMap,
  },
};
// Create your host
const host = LiveShareHost.create();
// Create the LiveShareRuntime, which is needed for `LiveDataObject` instances to work
const runtime = new LiveShareRuntime(this._host);
// Inject the LiveShareRuntime dependency into the ContainerSchema
const injectedSchema = getLiveShareContainerSchemaProxy(
    schema,
    runtime,
);
// Create (or get) your container
const { container } = await client.createContainer(injectedSchema);

// ... ready to start app sync logic

或者,可以使用或替代 AzureLiveShareHost。 这允许你从 AzureAudience获取自定义用户显示名称和角色,而不是通过 Microsoft Teams 获取。

import {
  LiveShareClient,
  LivePresence,
  AzureLiveShareHost,
  getLiveShareContainerSchemaProxy,
} from "@microsoft/live-share";
import { SharedMap } from "fluid-framework";
import {
  AzureFunctionTokenProvider,
  AzureClient,
} from "@fluidframework/azure-client";

// Define a custom connection for your app
const options = {
  connection: {
    tenantId: "MY_TENANT_ID",
    tokenProvider: new AzureFunctionTokenProvider(
      "MY_SERVICE_ENDPOINT_URL" + "/api/GetAzureToken",
      { userId: "userId", userName: "Test User" }
    ),
    endpoint: "MY_SERVICE_ENDPOINT_URL",
    type: "remote",
  },
};
// Initialize your AzureClient instance
const client = new AzureClient(options);
// Define your Fluid schema
const schema = {
  initialObjects: {
    presence: LivePresence,
    ticTacToePositions: SharedMap,
  },
};
// Create your AzureLiveShareHost
const host = AzureLiveShareHost.create();
// Create the LiveShareRuntime, which is needed for `LiveDataObject` instances to work
const runtime = new LiveShareRuntime(this._host);
// Inject the LiveShareRuntime dependency into the ContainerSchema
const injectedSchema = getLiveShareContainerSchemaProxy(
    schema,
    runtime,
);
// Create (or get) your container
const { container } = await client.createContainer(injectedSchema);
// Set AzureAudience into the AzureLiveShareHost
host.setAudience(services.audience);

// ... ready to start app sync logic

许多 Live Share API 依赖于全局时间戳 API,该 API 允许 LiveDataObject 对象确定远程消息的顺序。 如果使用依赖于 TimestampProvider 类的数据结构,则必须使用 LiveShareHost 库中的 teams-js ,或使用服务器返回的值替代 getTimestamp() 中的 AzureLiveShareHost 函数。

另请参阅