记一次celery worker hang debug

【写在前面】: 本文最终并没有debug出为什么卡住,虽然换了种方案解决了问题。

引入celery是为了调用京东api来做发货行为,以便提供给电商业务下快递单,然而在这个过程中,踩了一些坑(此文大概是2018年底的记录)

最初的配置,使用supervisor来管理celery进程,并且在代码更新之后,使用supervisorctl restart {$APP_NAME}来更新代码(celery并不支持gracefully reload,也暂时没有用其他更优雅的方案,待更深入的测试)

发现问题

线上的celery总是一段时间之后,就没有接受新的请求,celery beat还在发消息,python代码也在发消息存到broker(redis)里面,但消息一直没被消费

debug过程

  • 找出celery worker的pid,

    1
    2
    3
    4
    5
    www-data 6329 0.0 0.6 157228 50640 ? S 2018 0:03 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings beat -s /tmp/celerybeat-schedule --pidfile= -l info
    www-data 10004 0.1 0.6 162456 53804 ? S Jan02 4:12 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info
    www-data 18317 0.0 0.6 173032 56280 ? S Jan03 0:04 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info
    www-data 18318 0.0 0.6 166688 50220 ? S Jan03 0:00 /home/ubuntu/.pyenv/versions/3.7.1/envs/ems-admin-api/bin/python /home/ubuntu/.pyenv/versions/ems-admin-api/bin/celery -A settings worker --autoscale=8,4 -l info
    ...
  • 随便找一个worker的pid=10004,使用sudo strace -p 10004看看进程发生了什么事情,一直在recvfrom状态,等待接收数据

    1
    strace: Process 10004 attached recvfrom(23,
  • 那么我们可以使用lsof工具来看23是个什么东西:sudo lsof -p 10004 | grep 23

    1
    2
    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    python 10004 www-data 23u IPv4 81508763 0t0 TCP 172.16.0.17:47110->172.16.0.11:6379 (ESTABLISHED)

    我们是用腾讯云的VPC来部署Redis/MySQL等服务,那么这里的ip172.16.0.17是我们的云服务器,而172.16.0.11是我们的celery broker(redis)

  • 所以从上面的过程可以看出几个问题:

    1. 可以看出已经成功连接上redis broker,但并没有接收或者发送数据
    2. celery worker的工作持续时间为4:12,就停止了

而从celery worker output等相关日志也没看出什么问题

那么。。。最后我是换了celery的启动参数而已。

1
2
3
4
5
6
# 在supervisor中的启动参数
# 原本卡死的参数
celery -A config worker --autoscale=8,4

# 后来的参数
celery -A config worker -P gevent -c 4

也就是说,实际上我测试出来有变化的部分,就是把--autoscale=8,4去掉了,然后采用-P gevent -c 4来提供并发处理罢了。

至于autoscale为什么会挂,WHO KNOWS.