5

我们有一个 Web 服务,它为较大的 MP3 文件的固定库存中的小片段、任意片段提供服务。MP3 文件由 python 应用程序即时生成。该模型是,向指定您想要的段的 URL 发出 GET 请求,并获得一个audio/mpeg流作为响应。这是一个昂贵的过程。

我们使用 Nginx 作为前端请求处理程序。Nginx 负责缓存常见请求的响应。

我们最初尝试在后端使用 Tornado 来处理来自 Nginx 的请求。如您所料,阻塞的 MP3 操作使 Tornado 无法完成它的工作(异步 I/O)。所以,我们采用了多线程,这解决了阻塞问题,并且表现得很好。然而,它引入了一个微妙的竞争条件(在现实世界的负载下),我们还无法诊断或重现。竞争条件破坏了我们的 MP3 输出。

因此,我们决定将我们的应用程序设置为 Apache/mod_wsgi 后面的简单 WSGI 处理程序(仍然在前面使用 Nginx)。这消除了阻塞问题和竞争条件,但在现实世界条件下在服务器上创建了级联负载(即 Apache 创建了太多进程)。我们现在正在调整 Apache/mod_wsgi,但仍处于试错阶段。(更新:我们已经切换回 Tornado。见下文。)

最后,问题是:我们错过了什么吗?有没有更好的方法通过 HTTP 提供 CPU 昂贵的资源?

更新:感谢 Graham 的文章,我很确定这是一个 Apache 调优问题。与此同时,我们又回到了使用 Tornado 并试图解决数据损坏问题。

对于那些急于解决这个问题的人来说,Tornado 和一些多线程(尽管线程引入了数据完整性问题)可以在小型(单核)Amazon EC2 实例上可接受地处理负载。

4

5 回答 5

2

你试过产卵吗?它是一个 WSGI 服务器,具有多种灵活的线程模式。

于 2009-12-18T18:18:12.880 回答
1

您可能会考虑使用 AJAX 通知方法的排队系统。

每当有对昂贵资源的请求并且需要生成该资源时,将该请求添加到队列中(如果它尚不存在)。该排队操作应返回您可以查询以获取其状态的对象的 ID。

接下来,您必须编写一个启动工作线程的后台服务。这些工作人员只需将请求出列,生成数据,然后将数据的位置保存在请求对象中。

该网页可以对您的服务器进行 AJAX 调用,以了解生成的进度,并在文件可用时提供指向该文件的链接。

这就是大型媒体网站的工作方式——尤其是那些必须处理视频的网站。但是,这对您的 MP3 作品来说可能是多余的。

或者,考虑运行几台机器来分配负载。您在 Apache 上的线程仍然会阻塞,但至少您不会消耗 Web 服务器上的资源。

于 2009-12-18T17:46:05.680 回答
1

您是否犯了使用 Apache/mod_wsgi 的嵌入式模式的错误?读:

http://blog.dscpl.com.au/2009/03/load-spikes-and-excessive-memory-usage.html

如果使用 Apache/mod_wsgi,请确保使用守护程序模式。

于 2009-12-20T04:51:15.770 回答
1

请定义“级联负载”,因为它没有共同的含义。

如果您运行了太多 Apache 进程,则最可能出现的问题是。

对于这样的负载,请确保您使用的是 prefork mpm,并确保您将自己限制在适当数量的进程(每个 CPU 不少于一个,不多于两个)。

于 2009-12-20T22:48:36.053 回答
0

看起来你做对了——只是缺乏 CPU 能力:你能确定在生成这些 MP3 的过程中 CPU 负载是多少吗?

我认为您接下来要做的就是添加更多硬件以在其他机器上呈现 MP3。或者找到一种方法来提供预渲染的 MP3(也许你可以cahce 你的一些媒体?)

顺便说一句,Web 扩展是 Jacob Kaplan-Moss 今年在 PyCon Brasil 上的主题演讲的主题,它远不是一个封闭的问题。需要处理的技术堆栈非常令人印象深刻-(尽管我找不到演示文稿的在线副本--对此感到抱歉)

于 2009-12-18T17:50:19.023 回答