你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Gridwich 云媒体系统

Azure Blob 存储
Azure 事件网格
Azure Functions
Azure 逻辑应用

Gridwich 管道借助 Azure 事件网格夹层和 Terraform 夹层这两种新方法来引入、处理、存储和交付媒体资产。

体系结构

Gridwich 体系结构有两个夹层,可满足异步事件处理和基础结构即代码的要求:

  • 事件网格夹层从外部 saga 工作流系统中抽象出远程和长时间运行的进程,例如媒体编码,方法是将它们夹在两个事件网格处理程序之间。 此夹层允许外部系统发送请求事件、监视计划事件,并等待可能在几分钟或几小时后到达的最终成功或失败响应。

    Diagram showing the Event Grid handler sandwich.

    下载此体系结构的 Visio 文件

  • Terraform 夹层是更新为支持基础结构即代码的多阶段 Terraform 模式。 分离基础结构和软件版本意味着必须先发布并运行 Azure Functions 应用,然后 Terraform 才能部署事件网格订阅。 为了满足这一要求,CI/CD 管道中有两个 Terraform 作业:

    Diagram showing the Terraform sandwich jobs.

    • Terraform 1 创建除 Azure 事件网格订阅之外的所有资源。
    • Terraform 2 在软件启动并运行后创建事件网格订阅。

    这样,Terraform 就可以完全管理和部署解决方案基础结构,即使在部署软件项目之前无法创建所有 Azure 资源

工作流

Gridwich 请求和响应流程涵盖以下请求:

  • 创建
  • 传输
  • 招待会
  • 分派给 Gridwich 组件
  • 确认和操作
  • 响应

以下步骤描述了外部系统与 Gridwich 之间的请求和响应过程。 在 Gridwich 中,外部系统是 MAM 和 saga 工作流编排系统。 有关 Gridwich 操作消息事件的确切格式,请参阅 Gridwich 消息格式

Diagram showing the Gridwich request-response process.

  1. 外部系统创建一个请求并将其发送到请求中转站。

  2. 请求中转站负责将请求分派给传统发布-订阅模型中的 Gridwich 请求侦听器。 在此解决方案中,请求中转站是 Azure 事件网格。 所有请求都使用事件网格事件架构封装。

  3. Gridwich Azure Functions 应用使用来自事件网格的事件。 为了提高吞吐量,Gridwich 将 HTTP 终结点定义为事件网格启动的推送模型,而不是 Azure Functions 提供的事件网格绑定轮询模型。

  4. Azure Functions 应用读取事件属性,并将事件分派给处理该事件类型和版本的 Gridwich 代码部分。

  5. 任何将处理当前请求的处理程序都使用通用 EventGridHandlerBase 类在收到请求时立即发送确认消息。 然后,处理程序将工作分派给派生类。

    Gridwich 请求工作流本质上可以是同步的或异步的。 对于易于执行和快速完成的请求,同步处理程序会在发送确认后几乎立即返回成功或失败事件。

    对于长时间运行的请求,异步处理程序会评估请求、验证参数并启动长时间运行的操作。 然后,处理程序返回“计划”响应,以确认它请求了工作活动。 完成工作活动时,请求处理程序负责为工作提供“成功”或“失败”完成事件。

    事件发布服务将确认、失败、计划或成功消息传达给事件网格请求中转站。

  6. Azure Function 中的事件发布者将响应事件发送到事件网格主题,该主题充当可靠的消息中转站。 外部系统订阅主题并使用消息。 事件网格平台提供其常规重试逻辑,用于发布到外部系统。

消息顺序

虽然“确认”先于“成功”和“计划”响应,但 Gridwich 不保证“计划”响应总是先于相应的“成功”响应。 有效的响应顺序可以是“确认”>“计划”>“成功”或“确认”>“成功”>“计划”。

请求失败数

请求失败的可能原因包括:错误请求、缺少先决条件、处理失败、安全异常或未处理的异常。 几乎所有失败都具有相同的消息形式,并包含原始操作上下文值。 常见的 EventGridHandlerBase 类通常通过 Azure 函数事件发布者接口向事件网格发送“失败”响应。 Application Insights 还通过结构化日志记录记录失败。

操作上下文

外部系统可能会每天、每小时或每秒生成数千个请求。 针对 Gridwich 的每个请求事件都必须包含名为 operationContext 的 JSON 对象属性。

如果请求包含操作上下文(如 {"id"="Op1001"}),则每个 Gridwich 响应必须包含相应的不透明操作上下文,无论请求是短时间运行还是长时间运行。 此操作上下文会持续到长时间运行请求的生存期。

响应要求适用于“对应”而不是“同一”JSON 对象。 Gridwich 功能(如上下文静音)利用外部系统以自上而下的方式处理返回的 JSON 对象这一事实。

具体而言,外部系统:

  • 不依赖于属性排序,因此 Gridwich 可能按不同的顺序发送回具有相同属性的对象。 例如:{"a":1,"b":2}{"b":2,"a":1}

  • 允许存在额外的属性,因此收到 {"b":2,"a":1} 的 Gridwich 可以有效地返回 {"a":1,"b":2,"~somethingExtra":"yes"}。 为了尽量减少冲突的可能性,Gridwich 在添加的属性名称前加上波浪号 (~) 前缀,例如 ~muted

  • 不依赖于 JSON 格式。 例如,没有关于空白填充可能落在 JSON 的字符串表示形式中哪个位置的假设。 Gridwich 通过压缩 JSON 对象的字符串表示形式中不需要的空格来利用不依赖于此格式的优点。 请参阅 JSONHelpers.SerializeOperationContext

saga 参与者和操作上下文

在 Gridwich saga 编排系统中,每个 saga 参与者为系统贡献一个或多个工作活动。 每个 saga 参与者独立于其他参与者工作,并且多个 saga 参与者可能对一个请求采取行动。

每个 saga 参与者都必须保留操作上下文,但可能会以不同的方式实现它。 例如:

  • 短时间运行的同步操作会保留操作上下文。
  • Azure 存储为大多数操作提供了一个名为 ClientRequestId 的不透明字符串属性。
  • 有些服务有 Job.CorrelationData 属性。
  • 其他云 API 提供与不透明操作上下文类似的概念,这些上下文可在发出进度、完成或失败信号时返回。

有关 saga 和 saga 参与者的详细信息,请参阅 saga 编排

同步和异步处理程序

系统中的每个事件处理程序都使用通用 EventGridHandlerBase 类来提供泛型服务,例如请求确认、失败处理和响应事件的发布。 事件发布服务将确认、失败、计划或成功消息传达给事件网格请求中转站。

计划处理当前请求的任何处理程序都必须在收到请求时提供确认。 基类立即发送确认消息,然后将工作分派给派生类。

Diagram showing the Acknowledgment message flow.

同步事件处理

对于易于执行和快速完成的请求,处理程序同步完成工作,并在发送确认后几乎立即返回“成功”事件及其操作上下文。

Diagram showing a synchronous request-response message flow.

例如,ChangeBlobTierHandler 是一个简单的同步流。 处理程序获取请求数据传输对象 (DTO),调用并等待单个服务执行工作,并返回“成功”或“失败”响应。

Diagram showing the ChangeBlobTierHandler synchronous flow example.

异步事件处理

某些请求长时间运行。 例如,编码媒体文件可能需要几个小时。 在这些情况下,异步请求处理程序会评估请求、验证参数并启动长时间运行的操作。 然后,处理程序返回“计划”响应,以确认它请求了工作活动。

Diagram showing an asynchronous request-response message flow.

完成工作活动时,请求处理程序负责为工作提供“成功”或“失败”完成事件。 在保持无状态的同时,处理程序必须检索原始操作上下文并将其放入“完成”事件消息负载中。

例如,BlobCopyHandler 显示一个简单的异步流。 处理程序获取请求 DTO、调用并等待单个服务启动工作,并发布“计划”或“失败”响应。

Diagram showing the BlobCopyHandler asynchronous flow example with event scheduled.

若要完成长时间运行的请求流,BlobCreatedHandler 将使用平台事件 Microsoft.Storage.BlobCreated,提取原始操作上下文,并发布“成功”或“失败”完成响应。

Diagram showing the BlobCopyHandler asynchronous flow example with event successful.

长时间运行的函数

当 Gridwich 部署新的 Functions 应用时,它可能会删除当前长时间运行的进程。 如果这些进程突然结束,则没有状态,也不会向调用者报告。 Gridwich 必须部署新的 Functions 应用,同时正常处理长时间运行的函数的转换,并且不会丢失任何消息。

解决方案必须:

  • 不保持 Gridwich 应用程序运行实例的状态。
  • 不只是因为正在部署新内容或新消息请求相同的活动而终止进程。
  • 不调用任何其他 Azure 工作负载,如 Durable Functions、Functions 应用、逻辑应用或 Azure 容器实例。

Gridwich 使用 Azure Functions 槽部署和取消令牌来满足可靠且长时间运行的函数的这些要求。

下图显示了大多数 Gridwich 作业的工作方式。 绿色框表示 Gridwich 传递给外部服务的作业。 然后,Gridwich 以事件驱动的方式对状态做出反应。 红框显示了一个在 Gridwich 本身上长期运行的函数。

Diagram showing short-running and long-running functions.

当应用程序关闭时,Functions 运行时会添加取消令牌。 Gridwich 会检测该令牌,并返回所有请求和当前正在运行的进程的错误代码。

槽部署会部署新的软件版本。 生产槽具有正在运行的应用程序,过渡槽具有新版本。 Azure 执行一系列部署步骤,然后交换槽实例。 旧实例作为进程的最后一步重启。

Gridwich 在重新映射主机名后等待 30 秒,因此对于 HTTP 触发的函数,Gridwich 保证在旧生产槽重启前等待至少 30 秒。 其他触发器可能由没有等待应用设置更新机制的应用设置控制。 如果在旧生产槽重启之前开始执行,这些函数将面临中断的风险。

有关详细信息,请参阅 Azure Functions 槽交换期间发生的情况Azure Functions 部署槽

组件

Gridwich 媒体处理解决方案使用 Azure 事件网格、Azure Functions、Azure Blob 存储、Azure 逻辑应用和 Azure 密钥保管库。 CI/CD 和 saga 编排进程使用 Azure Repos、Azure Pipelines 和 Terraform。

  • Azure 事件网格管理 Gridwich 事件的路由,其中包含两个允许异步处理媒体事件的夹层事件网格作业。 事件网格是一个高度可靠的请求交付终结点。 Azure 平台提供必要的请求交付终结点正常运行时间和稳定性。

    Gridwich 将事件封装在事件网格架构Event.Data属性对象中,该对象对事件网格中转站和传输层是不透明的。 Gridwich 还使用 eventTypedataVersion 对象字段来路由事件。 因此,事件网格请求中转站可以用其他发布-订阅事件中转站代替,Gridwich 依赖于尽可能少的事件字段,并且不使用 topicsubject 字段。

  • 使用 Azure Functions 可以运行事件触发的代码,而无需显式预配或管理基础结构。 Gridwich 是一个 Azure Functions 应用,用于托管各种函数的执行。

  • Azure Blob 存储为非结构化数据(如媒体资产)提供经济高效的可缩放云存储和访问。 Gridwich 同时使用 Azure 存储块 blob 和容器。

  • Azure Key Vault 保护 Azure 和第三方应用和服务使用的加密密钥、密码和其他机密。

  • Azure DevOps 是一组开发人员和运营服务,包括基于 Git 的代码存储库和与 Azure 集成的自动化生成和发布管道。 Gridwich 使用 Azure Repos 来存储和更新代码项目,并使用 Azure Pipelines 来存储 CI/CD 和其他工作流。

  • Terraform 是一种开源工具,它使用基础结构即代码来预配和管理基础结构和服务。

备选方法

  • Durable Functions(具有用于长时间运行的操作的内置状态存储)也可以提供不透明的操作上下文。 Durable Functions 可以在操作中创建一系列任务,并将操作上下文保存为操作的输入或输出。 事实上,Gridwich 可以将 Durable Functions 用于所有工作活动,但这种方法会增加代码复杂性。

  • 可以通过将 EventGridHandlerBase 重构为 RequestHandlerBase 并删除与事件网格对象或类型的任何链接来实现与事件网格基础结构的更好解耦。 此重构类仅在基 DTO 中处理,而不适用于特定于传输的对象类型。 同样,IEventGridDispatcher 可以成为具有特定 EventGridDispatcher 实现的 IResponseDispatcher

  • Gridwich.SagaParticipants.Storage.AzureStorage 库还包含其他 saga 参与者使用的存储服务。 在核心项目中使用接口可以避免控制反转 (IoC) 问题,但你可以将接口提取到单独的核心存储基础结构网关库中。

  • Gridwich Functions 应用使用依赖项注入为特定事件类型和数据版本注册一个或多个请求处理程序。 应用将 EventGridDispatcher 注入事件网格事件处理程序的集合,调度程序查询处理程序以确定哪些处理程序将处理该事件。

    或者,可以使用事件网格平台提供的事件订阅和筛选机制。 此机制施加一对一部署模型,其中一个 Azure 函数仅托管一个事件处理程序。 尽管 Gridwich 使用一对多模型,但其简洁体系结构意味着重构一对一的解决方案并不困难。

  • 有关替代微服务,而不是单体 Gridwich 体系结构,请参阅微服务替代

方案详细信息

一家著名的大众媒体和娱乐集团将其本地视频流服务替换为了基于云的解决方案,用于引入、处理和发布视频资产。 该公司的主要目标是利用 Azure 云的容量、成本和灵活性来:

  • 引入、处理和发布原始视频文件,并满足媒体请求。
  • 使用清晰架构的方法,大规模改进编码以及新的引入和分发能力。
  • 为媒体资产管理 (MAM) 管道实现持续集成和交付 (CI/CD)。

为了实现这些目标,Microsoft 工程团队开发了 Gridwich,这是一个由外部 saga 工作流编排系统驱动的无状态事件处理框架。

可能的用例

工程团队开发了 Gridwich,以符合以下原则和行业标准:

Gridwich 系统体现了在 Azure 上处理和传送媒体资产的最佳做法。 虽然 Gridwich 系统特定于媒体,但消息处理和事件框架可以应用于任何无状态事件处理工作流。

部署此方案