django-celery 多服务器基础架构,使用 redis 作为代理

2 投票
2 回答
3487 浏览
提问于 2025-04-18 05:54

目前,我们所有的东西都设置在一台云服务器上,包括:

  • 数据库服务器
  • Apache(一个用来处理网站请求的服务器)
  • Celery(一个用来处理后台任务的工具)
  • Redis(一个快速的数据存储工具,用作Celery的消息中介,还有其他一些任务)
  • 等等

现在我们在考虑把主要的组件分开到不同的服务器上,比如单独的数据库服务器、存储媒体文件的服务器,以及在负载均衡器后面的网页服务器。这样做的原因是为了不再为一台性能强大的服务器付费,而是通过负载均衡器按需创建服务器,以降低成本并提高整体速度。

我对Celery的使用感到很困惑,有没有人曾经在多个生产服务器上使用Celery,并且在负载均衡器后面?任何指导都会很有帮助。

考虑一个小的使用案例,这就是目前在单台服务器上是如何操作的(我困惑的地方在于,当我们使用多台服务器时,这该如何实现):

  • 用户上传一个 abc.pptx 文件 -> 这个文件的引用被存储在数据库中 -> 文件存储在服务器的硬盘上
  • 创建一个任务(将文档转换为PDF),这个任务会放入Redis(消息中介)的队列中
  • 在同一台服务器上运行的Celery从队列中取出这个任务
    • 读取文件,使用一个叫 docsplit 的软件将其转换为PDF
    • 在服务器的硬盘上创建一个文件夹(这个文件夹将来会用作静态内容),把PDF文件、缩略图、纯文本和原始文件都放进去

考虑到以上的使用案例,如何设置多个网页服务器来执行相同的功能呢?

2 个回答

4

为了简化你的处理过程,使用一些共享存储是个好主意,这样所有合作的服务器都能访问到。这样设计后,你可以把工作分配给更多的服务器,而不用担心哪个服务器会处理下一个步骤。

使用AWS S3(或类似的)云存储

如果你能使用一些云存储,比如AWS S3,那就用它吧。

如果你的服务器也在AWS上运行,那么在同一区域内传输数据是免费的,而且速度也很快。

最大的好处是,你的数据可以在所有服务器之间共享,只要它们使用相同的桶(bucket)和键(key)名称,所以你不需要担心谁在处理哪个文件,因为大家都可以访问S3上的共享存储。

注意:如果你需要删除旧文件,可以在这个桶上设置一些策略,比如删除超过1天或1周的文件。

使用其他类型的共享存储

还有更多选择:

  • Samba
  • 中央文件服务器
  • FTP
  • 谷歌存储(和AWS S3非常相似)
  • Swift(来自OpenStack)
  • 等等。

对于小文件,你甚至可以使用Redis,但这种解决方案相对较少见,原因也很充分。

5

Celery 其实让这件事变得很简单,因为你已经在使用队列来处理任务。增加更多的工作者后,每个工作者会从队列中取出下一个任务,这样多个工作者就可以同时处理任务,每个工作者可以在自己的机器上运行。

这个过程有三个部分,而你已经有其中一个了。

  1. 共享存储,这样所有机器都可以访问相同的文件
  2. 一个可以把任务分配给多个工作者的中介 - redis 就可以用来做这个
  3. 在多台机器上运行的工作者

下面是如何设置的:

  • 用户将文件上传到前端服务器,前端服务器把文件存储在你的共享存储中(比如 S3、Samba、NFS 等),并在数据库中保存文件的引用
  • 前端服务器启动一个 celery 任务来处理这个文件,例如:

def my_view(request): # ... 处理文件存储 file_in_db = store_file(request) my_process_file_task.delay(file_in_db.id) # 使用数据库记录的主键 # 继续处理其他逻辑...

  • 在每台处理机器上,运行 celery-worker: python manage.py celery worker --loglevel=INFO -Q default -E

然后,当你增加更多的机器时,就会有更多的工作者,工作会在它们之间分配。

需要确保的关键点:

  • 你必须有共享存储,否则事情会变得复杂得多
  • 每台工作者机器必须有正确的 Django/Celery 设置,以便能够找到 redis 中介和共享存储(比如 S3 桶、密钥等)

撰写回答