我在EC2实例中运行一个Django应用程序,该应用程序使用RabbitMQ + Celery进行任务队列。从与生产应用程序相同的 EC2 实例运行 RabbitMQ 节点是否有任何缺点?
这个问题的答案实际上取决于应用程序的上下文。
当您遇到场景时,您应该始终考虑一些事情。
关注点分离 在这里,我们要确保如果其中一个系统不负责其他系统的运行。这包括诸如
-
如果运行所有内容的 ec2 实例出现故障,队列中的剩余任务是否会继续运行
-
如果我的 RAM 已满,所有系统都会保持正常运行吗
-
我是否可以只扩展应用的一个部分,而无需重新设计基础结构。
通过将兔子和姜戈(带有某种服务,wsgi,gunicorn,女服务员等)都放在一个盒子上,你会失去很多资源应急。
尽管 RAM 和 CPU 可能很丰富,但 IO、磁盘写入、网络写入等存在限制。这意味着,如果由于某种原因您的写入功能繁重,则所有其他系统可能会因此受到影响。如果您对 RAM 功能进行了大量写入,则同样适用。
因此,从您的问题和我自己的经验中可以看出,将事物保留在一个系统中的缺点如下。
-
多点故障。如果您的一个 rabbit 实例失败,您的队列和任务将停止工作。
-
如果您的应用程序开始产生大量流量,其他系统就会开始争夺资源。
-
如果任何组件出现故障,这可能意味着其他服务的其他停机时间。
-
系统停机时间意味着所有组件的完全停机时间。
-
当您的应用程序需要更多资源且停机时间最短时,会有很多麻烦。
-
大量网络流量会减慢任务运行速度
-
大量任务运行会减慢 Web 请求的速度
-
大量的IO会减慢所有事情的速度
我通常遵循的经验法则是使单点故障彼此远离 - 这样您只需要管理这些组件。一个很好的使用案例是为您的应用程序使用一个 EC2 实例,为您的工作人员使用另一个实例,为您的兔子使用另一个实例。这样,如果需要,您可以仅为这些组件应用更小/更大的实例。您甚至可以创建 AMI 并创建自动扩展组 - 如果这是您的使用案例。
以下是一些文章供参考
- 关注的分离
- 现代设计架构
- 单点故障
TLDR;如果你可以在一个EC2上运行,你应该这样做,但今天很容易扩展。
Joshnidhin 和 Giannis 都介绍了 RAM、IO 和 CPU 方面。
我已经使用容器化在单个实例中运行生产应用程序,并且放心地睡觉,如果明天突然有很多人想要我构建的东西,我可以通过将这些容器部署到不同的实例而不是单个实例上来快速扩展。
Docker允许您限制每个容器的CPU消耗和内存使用,因此您还可以确保它们不会相互影响。
如果我们把EC2实例从这个问题中剔除,它就会变成:
在与我的生产应用程序相同的服务器上运行 RabbitMQ 节点有什么缺点吗?
我会说这取决于各种事情,例如工作负载的类型及其组成,工作负载的复杂性,您是否期望使用量增长等。
如果您的工作负载运行良好,并且服务器足够大,可以同时容纳两者(应用程序 + 任务 q),那么为什么不呢,因为只有一台服务器需要管理。确保通过限制其系统资源使用来保护这两个进程。
如果您的流量表现不佳,那么您可能需要更多一台服务器。在这种情况下,拥有专用服务器更好(关注点分离),因为您必须管理多个服务器。
现在回到 EC2,以上所有内容仍然适用。EC2 使应用程序的水平扩展变得更加容易,因此,如果您将它们放在单独的实例上,那么您可以单独扩展它们并且经济高效地扩展它们。如果不是扩展时,就会浪费资源。