You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 21:57:55