django-celery 多服务器基础架构,使用 redis 作为代理
目前,我们所有的东西都设置在一台云服务器上,包括:
- 数据库服务器
- Apache(一个用来处理网站请求的服务器)
- Celery(一个用来处理后台任务的工具)
- Redis(一个快速的数据存储工具,用作Celery的消息中介,还有其他一些任务)
- 等等
现在我们在考虑把主要的组件分开到不同的服务器上,比如单独的数据库服务器、存储媒体文件的服务器,以及在负载均衡器后面的网页服务器。这样做的原因是为了不再为一台性能强大的服务器付费,而是通过负载均衡器按需创建服务器,以降低成本并提高整体速度。
我对Celery的使用感到很困惑,有没有人曾经在多个生产服务器上使用Celery,并且在负载均衡器后面?任何指导都会很有帮助。
考虑一个小的使用案例,这就是目前在单台服务器上是如何操作的(我困惑的地方在于,当我们使用多台服务器时,这该如何实现):
- 用户上传一个
abc.pptx
文件 -> 这个文件的引用被存储在数据库中 -> 文件存储在服务器的硬盘上 - 创建一个任务(将文档转换为PDF),这个任务会放入Redis(消息中介)的队列中
- 在同一台服务器上运行的Celery从队列中取出这个任务
- 读取文件,使用一个叫
docsplit
的软件将其转换为PDF - 在服务器的硬盘上创建一个文件夹(这个文件夹将来会用作静态内容),把PDF文件、缩略图、纯文本和原始文件都放进去
- 读取文件,使用一个叫
考虑到以上的使用案例,如何设置多个网页服务器来执行相同的功能呢?
2 个回答
为了简化你的处理过程,使用一些共享存储是个好主意,这样所有合作的服务器都能访问到。这样设计后,你可以把工作分配给更多的服务器,而不用担心哪个服务器会处理下一个步骤。
使用AWS S3(或类似的)云存储
如果你能使用一些云存储,比如AWS S3,那就用它吧。
如果你的服务器也在AWS上运行,那么在同一区域内传输数据是免费的,而且速度也很快。
最大的好处是,你的数据可以在所有服务器之间共享,只要它们使用相同的桶(bucket)和键(key)名称,所以你不需要担心谁在处理哪个文件,因为大家都可以访问S3上的共享存储。
注意:如果你需要删除旧文件,可以在这个桶上设置一些策略,比如删除超过1天或1周的文件。
使用其他类型的共享存储
还有更多选择:
- Samba
- 中央文件服务器
- FTP
- 谷歌存储(和AWS S3非常相似)
- Swift(来自OpenStack)
- 等等。
对于小文件,你甚至可以使用Redis,但这种解决方案相对较少见,原因也很充分。
Celery 其实让这件事变得很简单,因为你已经在使用队列来处理任务。增加更多的工作者后,每个工作者会从队列中取出下一个任务,这样多个工作者就可以同时处理任务,每个工作者可以在自己的机器上运行。
这个过程有三个部分,而你已经有其中一个了。
- 共享存储,这样所有机器都可以访问相同的文件
- 一个可以把任务分配给多个工作者的中介 - redis 就可以用来做这个
- 在多台机器上运行的工作者
下面是如何设置的:
- 用户将文件上传到前端服务器,前端服务器把文件存储在你的共享存储中(比如 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 桶、密钥等)