使用AWS ELB和RabbitMQ进行Celery连接

Dov*_*Dov 15 python rabbitmq amazon-web-services celery

在我们的环境中,我们在AWS上使用RabbitMQ和Celery在许多节点上并行运行任务.

最近,我们将RabbitMQ转换为3个节点的集群,配置了ha策略,并为所有3个节点添加了端口5672的AWS弹性负载均衡器(ELB).我们的Celery工作者和客户端代码都使用ELB DNS作为代理URL.

我们注意到,自那次更改以来,等待异步任务完成将引发异常IOError: Socket closed.

ELB将在60秒后关闭所有空闲连接.我们的任务需要几个小时才能完成.

将BROKER_HEARTBEAT设置为低于60的值可解决工作端的连接丢失问题.但我们似乎无法找到任何可以保持客户端连接活动的设置.

这是等待Celery长时间运行任务的正确方法吗?

我们尚未测试的一种解决方法是在AsyncResult.wait()方法成功结束之前重新调用该方法.例如:

async_result = task.delay(params)

while True:
    try:
        async_result.wait()
        break
    except IOError:
        pass
Run Code Online (Sandbox Code Playgroud)

我们用:

  1. RabbitMQ 3.6.5
  2. 芹菜3.1.20
  3. 芹菜后端是pyamqp
  4. 芹菜结果后端是rpc

Ale*_*ias 3

我相信你需要做的是延长AWS ELB的超时时间。发生的情况是连接在任务完成之前关闭。您可以通过发出以下命令来完成此操作

elb-modify-lb-attributes myTestELB --connection-settings "idletimeout=3600" --headers
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个小时的时间来完成任务。有关详细信息,请参阅https://aws.amazon.com/blogs/aws/elb-idle-timeout-control/ 。

如果一个小时还不够,那么您将不得不禁用连接池。将这两个设置添加到您的 celery 配置中

BROKER_POOL_LIMIT = None
BROKER_TRANSPORT_OPTIONS = {'confirm_publish': True}
Run Code Online (Sandbox Code Playgroud)

其次会影响性能,因为它增加了一些开销。由于您有长时间运行的任务,这可能不是问题。第二个设置可能不是必需的,但我建议您使用负载均衡器。此设置将确保消息被接收并且在此过程中不会丢失。

另一种选择是将您的长任务也分解为较小的任务!这可能意味着更多的代码,但从长远来看可能是值得的。