Heroku上NGINX+Django+uWSGI+Daphne的ASGI/WSGI运行与连接问题
Heroku上Django+NGINX+uWSGI+Daphne部署问题:NGINX启动失败与WebSocket连接异常
问题现状
在Heroku部署Django项目,计划通过NGINX反向代理同时运行WSGI(uWSGI)和ASGI(Daphne)服务,遇到以下问题:
- NGINX无法启动,web进程每秒重复输出日志:
buildpack=nginx at=app-initialization - Daphne进程启动失败,报错:
CRITICAL Listen failure: Couldn't listen on unix:/tmp/nginx.socket:48560: [Errno -2] Name or service not known.
当前WSGI(uWSGI)和Celery服务可正常运行,静态/媒体资源配置问题暂未处理。
现有配置
Procfile
release: python manage.py migrate web: bin/start-nginx-debug uwsgi uwsgi.ini daphne: daphne my_project.asgi:application --port $PORT --bind unix:/tmp/nginx.socket -v2 worker: celery -A my_project worker -l info
nginx.conf.erb
daemon off; # Heroku dynos have at least 4 cores. worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>; events { use epoll; accept_mutex on; worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>; } http { gzip on; gzip_comp_level 2; gzip_min_length 512; gzip_proxied any; # Heroku router sends Via header server_tokens off; log_format l2met 'measure#nginx.service=$request_time request_id=$http_x_request_id'; access_log <%= ENV['NGINX_ACCESS_LOG_PATH'] || 'logs/nginx/access.log' %> l2met; error_log <%= ENV['NGINX_ERROR_LOG_PATH'] || 'logs/nginx/error.log' %>; include mime.types; default_type application/octet-stream; sendfile on; # Must read the body in 5 seconds. client_body_timeout 5; # upstream for uWSGI upstream uwsgi_app { server unix:///tmp/nginx.socket; #unix:/app/my_project/uwsgi_app.sock; # } # upstream for Daphne upstream daphne { server unix:///tmp/nginx.socket; #unix:/app/my_project/daphne.sock; } server { listen <%= ENV["PORT"] %>; server_name _; keepalive_timeout 5; location / { # Uncomment this if statement to force SSL/redirect http -> https if ($http_x_forwarded_proto != "https") { return 301 https://$host$request_uri; } proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://127.0.0.1:8000; #//uwsgi_app; #include /etc/nginx/uwsgi_params; #uwsgi_pass uwsgi_app; } location /init-nginx/ { internal; proxy_pass http://127.0.0.1:8000; } location /ws/ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_pass http://daphne; } location /static/ { alias /app/my_project/static/; } location /media/ { alias /app/my_project/media/; } } }
问题解决与配置修正
1. 修复Daphne的Unix Socket错误
Daphne启动命令存在两个核心错误:
- Unix Socket路径后附加了端口号(
:48560),Unix Socket是文件路径,不需要端口 - 同时指定
--port $PORT和Unix Socket,Heroku的$PORT只能被一个进程监听(web进程的NGINX已占用)
修正后的Daphne启动命令:
daphne: daphne my_project.asgi:application --bind unix:/tmp/daphne.sock -v2
2. 实现touch /tmp/app-initialized满足NGINX启动要求
heroku-buildpack-nginx要求后端服务就绪后创建/tmp/app-initialized文件,有两种实现方式:
方式一:通过uWSGI配置钩子
在uwsgi.ini中添加post-fork钩子,uWSGI启动完成后自动创建文件:
post-fork = touch /tmp/app-initialized
方式二:在Django的WSGI入口添加代码
修改wsgi.py,在文件末尾添加:
import os # 标记应用已就绪,触发NGINX启动 if not os.path.exists('/tmp/app-initialized'): with open('/tmp/app-initialized', 'w') as f: f.write('')
3. 修正NGINX与服务的通信配置
- 分离Unix Socket:uWSGI和Daphne需要使用独立的Unix Socket,避免冲突
- 修正upstream配置:
# upstream for uWSGI upstream uwsgi_app { server unix:///tmp/uwsgi.sock; } # upstream for Daphne upstream daphne { server unix:///tmp/daphne.sock; }
- 修正根路径转发:将根路径请求转发给uWSGI的upstream,而非直接指向127.0.0.1:8000:
location / { # 保留原有SSL重定向等配置 if ($http_x_forwarded_proto != "https") { return 301 https://$host$request_uri; } include /etc/nginx/uwsgi_params; uwsgi_pass uwsgi_app; }
- 配置uWSGI监听对应Socket:在
uwsgi.ini中添加:
socket = /tmp/uwsgi.sock chmod-socket = 666 # 赋予NGINX读写权限
4. WebSocket连接问题的说明
NGINX正常启动并完成上述配置后,/ws/路径的请求会被正确转发到Daphne服务,且已配置WebSocket所需的Upgrade和Connection请求头,WebSocket连接问题应该可以解决。
内容的提问来源于stack exchange,提问作者a.jones
相关产品推荐
相关产品推荐

