我如何 运行 另一个 EC2 实例上的部分代码

How I Can Run Some Part of the Code on another EC2 instance

我在 EC2 实例 上有一个 NodeJS 应用程序 运行ning,它具有一些用户可以录制多个视频的功能。

当用户注销时,我正在使用 (版本 4.2.4)将所有这些视频组合成一个视频。

我录制的是WEBM格式的视频,最后的单视频应该是MP4格式的。

假设用户录制了 3 个视频,每个视频 10 分钟,那么最后当用户退出时,所有这 3 个视频应该合并为一个长度为 30 分钟的视频。

现在一切正常,但是当所有对话和连接都在进行时,CPU 使用率很高。

CPU 使用率有时高达 60-70%

我遵循的过程是

  1. webm 文件转换为 mp4 文件。

    ffmpeg -i input_file.webm -c:v copy -c:a copy output_file.mp4
    
  2. 将 MP4 转换为 ts(传输流)文件。

     ffmpeg -i output_file.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts OUTPUT_MP4.ts
    

    我正在按照这个过程将所有 mp4 文件连接成一个文件。

  3. 连接文件

    ffmpeg -i "concat:OUTPUT_MP4_1.ts|OUTPUT_MP4_2.ts|OUTPUT_MP4_3.ts" -c copy -bsf:a aac_adtstoasc FINAL_MP4_SINGLE_FILE.mp4
    

所有这个过程都很耗时(但不是优先级),但是,这个过程占用了 CPU 很多。

如果我的应用程序上有很多用户并且可能正在进行视频转换,服务器可能会崩溃或变慢。

现在,我的问题是如何 运行 在 专用 EC2 instance 上进行此转换过程,其中只能进行转换而不能进行任何其他工作,来自与第一个 EC2 实例 运行ning 相同的代码。

您将需要一个后处理任务的工作队列。一个简单的 Javascript 数组可以用作队列:您 .push() 将新项目放入队列,然后 .shift() 将它们取出以使用它们。

您将需要一个循环函数来使用队列,看起来像这样。

async function convertVideo (queue, completed) {
  while (true) {
    if (queue.length === 0) {
      await sleep(1000)
      continue
    }
    const item = queue.shift()
    await convertItem(item)
    completed.add(item)
  }
}
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

此函数将 运行 您的 convertItem() 一次作用于一项。在程序启动时调用此函数一次。给它排队。 我扔了一个 Set 来存放完成的项目。

const queue = []
const completed = new Set()
convertVideo(queue, completed).next()

您可能希望以不同的方式处理完成。

这不是 运行 不同虚拟机上的转换。但它确实可以防止您的单个实例过载。

您可以通过以下方式增加容量:

  • 向您的 VM 添加核心,运行 convertVideo 函数两次以获得两个并发转换操作。
  • 添加具有相同服务器软件的新 VM 并平衡传入请求。

如果您必须 运行 在不同的 VM 上进行转换,您需要某种 VM 间排队方案,以便您的 Web 服务器计算机可以将工作项传递给转换机器。 Amazon SQS, redis, and RabbitMQ 是 VM 间排队技术的可能选择。还有其他人。如果不深入了解您的应用程序的工作方式,就很难给出详细的建议。

如果你使用单独的虚拟机进行处理,你会发现AWS弹性转码服务已经解决了所有关于排队的操作细节。它很昂贵,但 24x7 全天候运行多核 EC2 实例也是如此。