3

我正在运行一个由于大量图像缩略图而占用大量 CPU 资源的网站。

这就是我目前做事的方式:

  1. 用户上传图片到服务器
  2. 服务器保留一个副本,并将图像存储在 Amazon S3 上
  3. 当请求缩略图时,服务器使用本地副本生成它,然后将其存储在 S3 上;然后将 S3 URL 提供给客户端
  4. 后续请求优化如下: 服务器将 S3 URL 缓存在 memcached 中,因此不再做该工作;如果文件存在,服务器将不再生成缩略图;服务器使用中等大小的缩略图来生成小尺寸的,所以不要处理不必要的大文件

现在,我托管在一个 Linode 4G 实例(8 核,4x 优先级,4GB RAM)上,尽管我进行了优化并且内存缓存命中率为 70%,但我的平均 CPU 为 170%。我经常看到所有 8 个 CPU 同时以 100% 的频繁峰值工作。

我正在使用 nginx 和 gunicorn 来为 Django 应用程序提供服务,并且缩略图是使用 PIL 生成的。

我该如何改进这个架构?

我想了几个可能性:

#1。最简单:添加第二个相同的服务器,前面有一个负载均衡器,这样他们就可以分担负载。

这样做的问题是两台服务器不会共享本地图像缓存。我可以通过将此类共享放在网络驱动器上来解决这个问题,还是延迟最终会阻碍收益?

#2。更难一点:将缩略图代码从我的应用程序中分离出来,作为一个单独的 Web 服务,它将在第二台服务器上运行。这样主应用程序和数据库就不会受到高 CPU 使用率的影响,并且可以快速提供网页。无论如何,缩略图已经与 JavaScript 异步提供

任何人都可以推荐其他解决方案吗?

4

2 回答 2

1

您确定您的性能问题来自缩略图吗?好的,我想你已经检查过了。

您可以在用户上传图像后立即(或不久)缩小 2 个缩略图并将其上传到 S3。通过这种方式,您应该能够节省您现在为每个 HTTP 请求检查这些缩略图并使用 memcached 进行 IPC 所浪费的不必要的 CPU 负载。

于 2013-11-05T18:13:47.693 回答
0

在某种程度上,您的问题是一个“好”的问题(或者至少它可能会更糟),因为单独的图像大小调整任务之间没有依赖关系,因此您可以轻松地将它们分布在多个服务器上。几点评论:

  1. 您是否检查过是否可以采取任何措施来加快图像大小调整操作?(谷歌提出来了,不知道有没有帮助:http ://dmmartins.appspot.com/blog/speeding-up-image-resizing-with-python-and-pil )即使你仍然发现你需要要添加更多服务器,您可以采取任何措施使每次调整大小操作更高效,从而使每台服务器走得更远。

  2. 如果您的用户越来越多,您最终将需要“横向扩展”,但在短期内,您可能只需为下一个“层”服务(8 核8 倍优先级)。

  3. 图片调整大小真的是您应用程序的唯一瓶颈吗?如果图像大小调整是“免费的”,那么在呈现页面、运行数据库查询等会限制吞吐量之前,您可以在现有服务器上进一步扩展多少?如果您不知道,最好进行一些模拟负载测试并找出答案。我问是因为如果渲染页面、数据库查询等也是瓶颈,或者很快就会成为瓶颈,那么无论如何你都必须分发应用程序。在这种情况下,您最好在主应用程序中保留缩略图,并立即分发它,而不是让您的缩略图在第二台服务器上作为 Web 服务运行。

  4. 无论您是分发主应用程序,还是将缩略图拆分到不同服务器上的单独应用程序中,您都需要某种权威存储来跟踪每个缩略图在 S3 上的保存位置。您可以将该信息保存在 memcached、数据库或任何您想要的位置。这并不重要。即使您将其保存在 memcached 中,这并不意味着您不能在 2 台服务器之间共享缓存——一台服务器可以连接到另一台服务器上运行的 memcached 实例。

您询问检查保存在不同服务器上的缓存的“延迟”是否会“阻碍收益”。我认为你不必担心这一点。您的问题是吞吐量,而不是延迟。那些高延迟的网络操作可以很好地并行化。因此,如果您只是并行处理更多请求,您仍然可以充分利用您的 CPU(这是目前的资源瓶颈)。

于 2013-11-05T20:47:55.487 回答