如何在 NodeJS 中处理 CPU 密集型任务的多个请求?

How to handle multiple requests for CPU intensive tasks in NodeJS?

在我的 NodeJS 中,有一个巨大的处理任务,包括从 IBM 云下载大约 600MB 的音频文件(8-10 个音频,每个大约 70MB),然后使用 FFMPEG https://www.npmjs.com/package/ffmpeg.音频处理需要大约 5 分钟的大量时间。这个过程是异步的,所以我的前端会响应。

如何处理对同一音频处理的多个请求,但问题是多个请求将有不同的音频要下载和处理,因此在处理多个请求时可能会出现竞争条件。通过阅读其他堆栈溢出答案,我了解到有创建子进程或工作线程等方法。适合我的用例的方法是什么?我如何确保不满足竞争条件?

背景

我有过类似的经历,不过是视频转换和处理。我不得不使用 ffmpeg 将视频转换为不同的容器和质量格式。

解决方案

对于我的场景,解决此问题的最佳方法是创建一个作业队列。我使用了 celery 并且它能够很好地处理它。

您的用例的等效项是 - https://github.com/mher/node-celery

您将不得不产生一些工作人员,这些工作人员将从 RabbitMQ 等消息队列数据库中分配任务。任务完成后,他们异步发回响应。希望这适用于你的场景

从 ffmpeg 模块的文档中我们看到:

This library provides a set of functions and utilities to abstract commands-line usage of ffmpeg.

看了下ffmpeg模块的源码,发现实现的核心是这样的:

utils.exec([ffmpeg.bin,'-formats','2>&1'], settings, ...

其中utils.exec基本上是这样的:

child_process.exec(finalCommand, settings, ...

所以基本上 ffmpeg 模块已经在使用子进程来执行 CPU 密集型任务。这意味着 node.js 没有执行任何 CPU 密集型任务。

这意味着您不需要做任何额外的事情来处理多个请求。您执行的任何其他操作只会使用更多 RAM,而不会带来任何性能优势。

如何缩放:

缩放这在任何语言中都是相同的,因为您的服务器基本上已经 multi-threaded/multi-processing。只需使用具有更多内核的 CPU。

扩展超越 CPU:

Netflix 和 YouTube 等大型服务可以并行处理数以万计的媒体。显然你买不到几万核的CPU。扩展的方式是在多个 CPUs/servers 之间对服务进行负载平衡,而不是直接使用 ffmpeg:

 ┌─────────────────┐           ┌─────────────────────┐
 │ node web server │ --------> │ node ffmpeg servers │┐
 └─────────────────┘           └┬────────────────────┘│┐
                                └┬────────────────────┘│
                                 └─────────────────────┘