在我们的环境中,我们在AWS上使用兔子和芹菜在许多节点上并行运行任务。
最近,我们将RabbitMQ变成了3个节点的群集,配置了HA策略,并为所有3个节点添加了端口5672的AWS弹性负载平衡器(ELB)。我们的芹菜工人和客户代码都使用ELB DNS作为经纪人URL。
我们已经注意到自变更以来,等待异步任务完成的等待将抛出一个例外IOError: Socket closed
。
ELB将在60秒后关闭所有空闲连接。我们的任务需要几个小时才能完成。
将Broker_HeartBeat设置为低于60个解决的连接下降的值。但是,我们似乎找不到任何可以使客户连接保持活力的设置。
这是等待使用芹菜长时间运行的任务的正确方法?
我们尚未测试的一个解决方法是回忆AsyncResult.wait()
方法,直到成功结束为止。因此:
async_result = task.delay(params)
while True:
try:
async_result.wait()
break
except IOError:
pass
我们使用:
- 兔子3.6.5
- 芹菜3.1.20
- 芹菜后端是pyamqp
- 芹菜结果后端是RPC
我相信您需要做的是扩展AWS ELB上的超时。发生的事情是在任务完成之前已经关闭连接。您可以通过发出以下命令
来完成此操作。elb-modify-lb-attributes myTestELB --connection-settings "idletimeout=3600" --headers
这将为您一个小时完成任务。有关此信息,请参见https://aws.amazon.com/blogs/aws/elb-idle timeout-control/有关此信息的更多信息。
如果一个小时还不够,那么您将必须禁用连接池。将这两个设置添加到您的芹菜配置
BROKER_POOL_LIMIT = None
BROKER_TRANSPORT_OPTIONS = {'confirm_publish': True}
第二次将添加一些开销,因为它会受到性能。由于您有长期运行的任务,这可能不是问题。第二个设置可能不是必需的,但是我建议您鉴于您落后于负载平衡器。此设置将确保在此过程中收到消息并且不会丢失。
另一个选择也将您的长任务分解为较小的任务!这可能意味着更多代码,但从长远来看可能值得。