芹菜在长时间不活动后意外关闭

时间:2014-01-06 17:08:15

标签: python django ubuntu rabbitmq celery

所以我使用RabbitMQ + Celery来创建一个简单的RPC架构。我有一个RabbitMQ消息代理和一个运行Celery deamon的远程工作者。

第三台服务器公开了一个瘦RESTful API。当它收到HTTP请求时,它会向远程工作人员发送一个任务,等待响应并返回响应。

这在大多数情况下都很有效。但是我注意到,在长时间不活动(比如5分钟没有传入请求)之后,Celery工作人员表现得很奇怪。经过较长时间不活动后收到的前3个任务会返回此错误:

exchange.declare: connection closed unexpectedly

在三个错误的任务之后,它再次起作用。如果没有较长时间的任务,则会发生同样的事情。有什么想法吗?

Celery工作者的初始化脚本:

# description "Celery worker using sync broker"

console log

start on runlevel [2345]
stop on runlevel [!2345]

setuid richard
setgid richard

script
chdir /usr/local/myproject/myproject
exec /usr/local/myproject/venv/bin/celery worker -n celery_worker_deamon.%h -A proj.sync_celery -Q sync_queue -l info --autoscale=10,3 --autoreload --purge
end script

respawn

我的芹菜配置:

# Synchronous blocking tasks
BROKER_URL_SYNC = 'amqp://guest:guest@localhost:5672//'
# Asynchronous non blocking tasks
BROKER_URL_ASYNC = 'amqp://guest:guest@localhost:5672//'

#: Only add pickle to this list if your broker is secured
#: from unwanted access (see userguide/security.html)
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'UTC'
CELERY_ENABLE_UTC = True
CELERY_BACKEND = 'amqp'

# http://docs.celeryproject.org/en/latest/userguide/tasks.html#disable-rate-limits-if-they-re-not-used
CELERY_DISABLE_RATE_LIMITS = True

# http://docs.celeryproject.org/en/latest/userguide/routing.html
CELERY_DEFAULT_QUEUE = 'sync_queue'
CELERY_DEFAULT_EXCHANGE = "tasks"
CELERY_DEFAULT_EXCHANGE_TYPE = "topic"
CELERY_DEFAULT_ROUTING_KEY = "sync_task.default"
CELERY_QUEUES = {
    'sync_queue': {
        'binding_key':'sync_task.#',
    },
    'async_queue': {
        'binding_key':'async_task.#',
    },
}

有什么想法吗?

编辑:

好的,现在它似乎是随机发生的。我在RabbitMQ日志中注意到了这一点:

=WARNING REPORT==== 6-Jan-2014::17:31:54 ===
closing AMQP connection <0.295.0> (some_ip_address:36842 -> some_ip_address:5672):
connection_closed_abruptly

2 个答案:

答案 0 :(得分:3)

您的RabbitMQ服务器或您的Celery工作者是否有可能落后于负载均衡器?如果是,则负载均衡器在一段时间不活动后关闭TCP连接。在这种情况下,您必须从客户端(工作人员)端启用心跳。如果你这样做,我不建议使用纯Python amqp lib。相反,请将其替换为librabbitmq

答案 1 :(得分:2)

如果客户端在没有正确的AMQP关闭协议的情况下断开连接,则会导致connection_closed_abruptly

channel.close(...)

  

请求关闭频道。

     

此方法表示发件人想要关闭频道。   这可能是由于内部条件(例如强制关闭)或由于   处理特定方法的错误,即异常。   当关闭是由异常引起时,发件人提供类和方法ID   导致异常的方法。

     

发送此方法后,必须丢弃除CloseClose-OK之外的任何接收方法。发送Close后收到Close的回复必须是Close-Ok

channel.close-ok():

  

确认关闭频道。

     

此方法确认Channel.Close方法并告知收件人   为渠道释放资源是安全的。

     

在未收到套接字关闭的情况下检测套接字关闭的对等体   频道。Close-Ok握手方法SHOULD记录错误。

Here是一个问题。

您可以为BROKER_HEARTBEATBROKER_HEARTBEAT_CHECKRATE设置自定义配置,然后再次检查,例如:

BROKER_HEARTBEAT = 10 
BROKER_HEARTBEAT_CHECKRATE = 2.0