创建可扩展的应用程序

CanCan 示例应用程序是一个简化的视频共享服务,它演示了您可以用作您自己的应用程序模型的几个功能。 例如,您可以通过探索 CanCan 示例应用程序了解以下几点:

  • 如何通过将内容拆分为片段以进行上传和存储,然后使用查询来检索和重组片段以实现高效的流式传输,从而构建可扩展的应用程序。

  • 如何为使用以不同后端语言编写的容器的应用程序配置互操作性。

  • 如何实现一个基本的认证模型来存储不同用户上传的视频。

  • 如何构建一个前端,为桌面或移动应用程序实现更复杂的用户界面功能。

将上传的内容拆分为多个容器

因为容器是编译的 WebAssembly 模块,所以它们具有某些已知的限制。 例如,当前 WebAssembly 模块的内存最大为 4GB,并且允许的对象调用数量有上限。

对于像 CanCan 这样的视频共享示例应用程序,这些限制意味着需要多个容器,并且必须将数据分成更小的块进行存储和检索。

实现分布式哈希表

为 Internet Computer 构建可扩展视频共享服务的最初尝试使用分布式哈希表 (DHT) 作为后端服务,该服务具有简单的 get 和 put 函数来分发数据(要上传或流式传输的视频块) 到一组预定义的容器中。 在项目的早期阶段,这种方法足以进行概念验证并验证视频数据是否可以正确转码以进行存储和检索。

但是,应用程序的可扩展性受到限制,因为分布式哈希表依赖于特定数量的容器,它可以填充数据以进行存储并从中检索数据以进行查看。 此外,分布式哈希表后端服务的原始实现包括用于解决可能导致节点不可用或丢失数据的常见网络连接问题的代码。

简化可扩展性

因为 Internet Computer 协议依赖于跨子网中节点的复制状态,所以它提供了有关容错和故障转移的某些保证,这些保证通常不适用于在其他平台或协议上运行的应用程序。

意识到 Internet Computer 可以确保容器可用于接收和响应请求,原来的分布式哈希表后端服务被称为 BigMap 的更简单但更具可扩展性的后端服务取代。

BigMap 提供了一个简单的插件库,用于使用 Internet 计算机上的键值存储构建可扩展的应用程序。 通过使用 BigMap 库作为后端服务,CanCan 示例应用程序可以动态地对数据进行分块、序列化和分发到多个容器。

该库为特定于应用程序的内存数据抽象提供了构建块,可使用任意数量的容器进行扩展。 每个容器的容量仍然有限,但应用程序会实例化它需要的容器,并在名为“manifest”的索引文件中跟踪构成每个用户视频的完整视频内容的片段。

BigMap 服务所需的代码比传统的分布式哈希表要简单得多,因为 Internet Computer 作为平台提供了可扩展性、复制、故障转移和容错功能。

展示互操作性

CanCan 示例应用程序存储库中包含的 BigMap 服务是用 Rust 编程语言编写的。 但是,CanCan 示例应用程序还演示了用不同语言编写的容器之间的互操作性。

在这种情况下,BigMap 功能是使用 Rust 编程语言实现的,而其他服务——例如视频内容的编码和解码以及用于身份验证的用户主体的管理——是使用 Motoko 实现的。

通过将示例应用程序的不同部分部署为容器,它们之间的交互提供了无缝的用户体验。

尽管您在 CanCan 存储库中看到的 BigMap 服务是用 Rust 编写的,但该服务实际上是用 Rust 和 Motoko 编程语言实现的,以演示以下内容:

  • 您可以在 Internet Computer 上运行作为容器部署的 Motoko 代码和 Rust 代码。

  • 您可以在后端语言之间切换,而不影响 CanCan 示例应用程序的运行。

  • 由于 Candid 语言提供了一种用于描述 BigMap API 的通用语言,独立于 JavaScript、Rust 或 Motoko,这两种语言的实现都可以无缝工作。

认证模型

与 LinkedUp 示例应用程序非常相似,CanCan 示例应用程序使用公私密钥对、基于浏览器的本地存储和 Principal 数据类型来验证用户身份。

实现前端功能

CanCan 示例应用程序使用 React 库结合 TypeScript 来实现前端用户界面。

数据模型概述

该应用程序存储有关用户的信息和有关视频的信息。 为了支持大多数浏览器,视频被序列化为字节数组,视频数据存储在 500kb 字节段中,称为link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects/Uint8Array[Uint8Array] 对象。 当请求视频时,清单会加载播放视频所需的块列表,并在将视频显示在标准 <video> 元素中之前连接这些块。

用户资料

用户配置文件存储为 profiles/{username} 并使用以下数据模型定义:

export interface Profile {
  username: string;         // maya
  following: string[];      // [`alice`, `bob]`
  followers: string[];      // ['palice']
  uploadedVideos: string[]; // ['profiles/maya/videos/a5b54646-2ea3-4e0e-82d1-da3ab8148df2']
  likedVideos: string[];    // ['profiles/bob/videos/b74e4eb0-dea8-4a4a-a1ae-d4593dc86930']
  avatar?: string;          // ?ImageData (TODO)
}

视频

上传的视频由存储在 profiles/{username}/videos/{videoId}public/videos(平台上所有现有视频的数组)中的唯一标识符标识。

视频的元数据存储在 profiles/{username}/videos/{videoId}/metadata 单个视频片段存储在 profiles/{username}/videos/{videoId}/chunks/chunk.{0-10}

视频存储为 profiles/{username} 并使用以下数据模型定义:

export interface Video {
  src: string;       // 'profiles/maya/videos/f5a44646-2ea3-4e0f-83d2-da3ab8148df2'
  userId: string;    // 'maya'
  createdAt: string; // Date.now()
  caption: string;   // 'cool movie, punk'
  tags: string[];    // ['outside', 'grilling', 'beveragino']
  likes: string[];    // ['sam', 'kelly']
  viewCount: number; // 102
  name: string; // 'grilling'
}