我有一个Django项目, 在这个项目中使用了celery执行异步任务,broker使用的是rabbitmq, 我在我的macbook运行一切正常,然后在CentOS的虚拟机中运行也没有问题,但是,当我使用docker部署这个项目时,如果我请求的一个view,这个view调用了一个celery task的daley方式时,就会被阻塞。
我创建了一个测试项目,放在我的github上: https://github.com/fengyoucha...。
Task
@shared_task
def add(x, y):
return x + y
其实还定义其他任务,但是在这个项目中的view中只调用这个task。
View
def index(request): # 映射 /
a = int(request.GET.get('a', 1))
b = int(request.GET.get('b', 2))
add.delay(a, b)
return HttpResponse("Hello world")
def hello(request): # 映射 /hello
return HttpResponse("hello")
这个项目使用了docker-compose部署,docker-compose.yml
定义了三个服务
- rabbitmq - rabbitmq 服务
- web - 执行
python mananage.py runserver 0.0.0.0:8000
- celery - 执行
celery -A proj worker -l info
使用docker-compose up
启动服务后
测试web服务
请求index
curl localhost:8000
此命令会阻塞,在index方法中的add.delay(a, b)
发生了阻塞
请求helle
curl localhost:8000/hello
返回内容“hello”, hello方法中并没有调用task的delay
方法
进一步测试
在物理机中执行启动proj这个项目,当然只启动web就行了,也就是运行python manage.py runserver
为了证明只有在docker运行web会阻塞, 这里要求其他环境都使用docker-compose.yml定义的服务
保留启动的celery和rabbit docker容器(也不用关闭docker中的web容器,其实就是什么也不需要做....)
我在docker-compose.yml中已经定义了rabbit的5672端口映射到物理机的5672端口,而在proj这个django项目中,通过读取环境变量RABBITMQ_HOST
来设置需要链接的rabbitmq server
proj中配置broker相关代码
RABBITMQ_HOST = os.environ.get("RABBITMQ_HOST", 'rabbitmq')
CELERY_BROKER_URL = 'amqp://guest:guest@%s//' % RABBITMQ_HOST
在物理机更改下环境变量,然后新起一个web
export RABBITMQ_HOST=localhost
python manage.py runserver 0.0.0.0:18000
访问该web的view
curl locahost:18000
该请求正常返回 “Hello world”, 同时celery容器中也打印出了执行add
任务的日志。
我的其他测试
我也进行了其他测试,例如:docker中启动web, 使用物理机中的rabbit,物理机中启动的celery, 一样会阻塞,
反正只要在docker中运行web,执行task的delay
方法就会发生阻塞。
最后
这个问题已经困扰很久,docker中部署使用了celery的Django项目,有谁有成功经验,或者我哪里配置有问题,望指教。
怎么还没有人回答呢,至今为解决