Nginx:运行 django 时,uWSGI 套接字出现 502 Bad Gateway 错误(111:连接被拒绝)

Nginx:运行 django 时,uWSGI 套接字出现 502 Bad Gateway 错误(111:连接被拒绝)

我正在使用 Nginx、uWSGI、Django 和 Postgresql 堆栈构建一个应用程序。该应用程序在 Nginx 和 uWSGI 之间使用 Unix 套接字。套接字上的文件权限为 775。但我仍然收到此权限错误:

[error] 6978#0: *6725 connect() to unix:/path/to/socket failed (111: Connection refused) while connecting to upstream, client: 54.250.253.225, server: example.com, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/path/to/socket:", host: "example.com"

Nginx 配置

# uWSGI upstream
upstream app{
    server  unix:/path/to/socket;
    }

# redirect www to non-www
server{
    listen  80;
    server_name www.example.com;
    return  301 http://example.com$request_uri;
}

# configuration of the server
server {
    # the port your site will be served on
    listen      80;
    # the domain name it will serve for

    # substitute your machine's IP address or FQDN
    server_name example.com
    charset     utf-8;

    # root folder
    root    /path/to/root;

    # max upload size
    client_max_body_size 20M;   # adjust to taste

    access_log  /path/to/access.log;
    error_log   /path/to/error.log;

    # Django media
    location /media  {
    # your Django project's media files - amend as required
    alias /path/to/media;  
    }

    location /static {
    # your Django project's static files - amend as required
    alias /path/to/static; 
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  app;
    # the uwsgi_params file you installed
    include     /path/to/uwsgi_params; 

    uwsgi_param Host $host;
    uwsgi_param X-Real-IP $remote_addr;
    uwsgi_param UWSGI_SCHEME $scheme;
    uwsgi_param SERVER_SOFTWARE nginx/nginx_version;
    }
}

我的虚拟环境中的文件已全部 chown 为 ubuntu:ubuntu。nginx 用户是 ubuntu。

uWSGI 日志

*** Starting uWSGI 2.0.12 (64bit) on [Sun Apr 17 17:24:37 2016] ***
compiled with version: 4.8.4 on 17 April 2016 14:40:25
os: Linux-3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:15 UTC 2016
nodename: ip-10-167-29-5
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /path/to/app
detected binary path: /path/to/bin/uwsgi
chdir() to /path/to/chdir
your processes number limit is 30035
your memory page size is 4096 bytes
 *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** 
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to UNIX address /path/to/socket fd 3
Python version: 3.4.3 (default, Oct 14 2015, 20:31:36)  [GCC 4.8.4]
Set PythonHome to /path/to/home
Python main interpreter initialized at 0xa4df10
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 436608 bytes (426 KB) for 5 cores
*** Operational MODE: preforking ***
/path/to/lib/python3.4/site-packages/cloudinary/models.py:24: RemovedInDjango110Warning: SubfieldBase has been deprecated. Use Field.from_db_value instead.
  return meta(name, bases, d)

WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0xa4df10 pid: 8567 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 8567)
spawned uWSGI worker 1 (pid: 8569, cores: 1)
spawned uWSGI worker 2 (pid: 8570, cores: 1)
spawned uWSGI worker 3 (pid: 8571, cores: 1)
spawned uWSGI worker 4 (pid: 8572, cores: 1)
spawned uWSGI worker 5 (pid: 8573, cores: 1)

有人能告诉我是什么导致了这个权限问题吗?

答案1

看起来 uWSGI 服务正在监听具有不同绝对路径的 Unix 套接字(由于chdir()调用)。您可以使用lsof | grep "/path/to/socket"来查找正在监听的 Unix 套接字的绝对路径。我猜是的/path/to/chdir/path/to/socket

答案2

我自己可以解决这个问题。我重启了服务器。然后我重启了 Nginx 和 uWSGI

sudo service nginx restart 
sudo service uwsgi restart

Nginx 重新启动后没有出现问题。但是,uWSGI 返回了此错误:

/etc/init.d/uwsgi: line 73: /usr/share/uwsgi/init/do_command: No such file or directory

我尝试切换到该目录。但是,它不存在。因此,我在 uwsgi 目录中创建了 init 目录,如下所示:

sudo mkdir init

然后我进入了新的目录:

cd init

在该目录中,我创建了 uWSGI 无法找到的文件:do_command。

sudo nano do_command

打开文件编辑器后,我粘贴了找到的文件:https://raw.githubusercontent.com/jbq/uwsgi/master/debian/uwsgi-files/init/do_command

# This is shell script, sourced by uWSGI init.d script

. /usr/share/uwsgi/init/snippets
. /usr/share/uwsgi/init/specific_daemon

do_command()
{
  local COMMAND="$1"
  shift

  local ERRORS=0

  # If command is given with arguments, i.e. 'start smth smth_else'
  if [ -n "$1" ]; then
    [ "x$VERBOSE" != "xno" ] && log_progress_msg "->"

    # Iterate over given configuration file specifications and:
    # * either print notice that conforming conffile wasn't found (if it
    #   wasn't)
    # * or execute given command with conforming conffile
    local CONFSPEC_PATH=""
    for CONFSPEC in "$@"; do
      CONFSPEC_RELPATH="$(relative_path_to_conffile_with_spec "$CONFSPEC")"
      if [ -z "${CONFSPEC_RELPATH}" ]; then
        log_progress_not_found "$CONFSPEC"
      else
        do_with_given_specific_daemon "$COMMAND" "$CONFSPEC_RELPATH"
        ERRORS="$(expr "$ERRORS" + "$?")"
      fi
    done

    [ "$ERRORS" -eq 0 ] && log_progress_done

    return "$ERRORS"
  fi

  # Do not start daemon if it was disabled.
  if [ "x$COMMAND" = "xstart" -a "x$RUN_AT_STARTUP" != "xyes" ]; then
    [ "x$VERBOSE" != "xno" ] && log_progress_msg "(disabled; see /etc/default/${NAME})"
    return 2
  fi

  local SOME_CONF_WAS_FOUND=no
  local UWSGI_APPS_CONFDIRS="$(ls -1d ${UWSGI_APPS_CONFDIR_GLOB})"

  # This construction is needed for supporting configuration file names with
  # spaces or control characters.
  #
  # See http://www.dwheeler.com/essays/filenames-in-shell.html (paragraph #4).
  #
  # Predefined delimeters are resetted to null character (by changing IFS and
  # setting -d option of 'read' command) and then:
  # * 'find -print0' command is used for finding all available confnames
  # * 'while ... read' loop is used for iterating over found confnames
  # 
  # Also process substitution is used, so that variables changed inside 'while'
  # loop will retain their values after exiting from loop.
  #
  # By default 'find' command use emacs-style regexps. Emacs-style regexp
  # processor with given regexp doesn't matches to file names with newline
  # character. Posix-style regexp processor is working good.
  #
  # With executing 'sed' over found paths, relative configuration file
  # paths are extracted from full paths provided with 'find' output.
  # Firstly, common directory path (UWSGI_CONFDIR) is stripped from 'find'
  # output. Secondly, all directories (except the first) and file extensions
  # are stripped from result of first substitution.
  #
  # For example: list of found paths
  # '/etc/uwsgi/apps-enabled/site.ini\0/etc/uwsgi/apps-enabled/dir/site2.ini'
  # is transformed by sed into 'apps-enabled/site\0apps-enabled/site2'.
  while IFS="" read -r -d "" RELATIVE_CONFPATH <&4 ; do
    if [ "x$SOME_CONF_WAS_FOUND" = "xno" -a "x$VERBOSE" != "xno" ]; then
      log_progress_msg "->"
    fi
    SOME_CONF_WAS_FOUND=yes
    do_with_given_specific_daemon "$COMMAND" "$RELATIVE_CONFPATH"
    ERRORS="$(expr "$ERRORS" + "$?")"
  done 4< <(find "$UWSGI_APPS_CONFDIRS" \
                  -regextype posix-basic \
                  -iregex ".*\.${UWSGI_CONFFILE_TYPES_REGEXP}\$" -a -xtype f \
                  -print0 \
            | sed -e "s:\(^\|\x0\)${UWSGI_CONFDIR}/:\1:g" \
                  -e "s:\([^\x0/]\+\)\([^\x0]\+\)\?/\([^/\x0]\+\)\.${UWSGI_CONFFILE_TYPES_REGEXP}\x0:\1/\3\x0:g" \
            | sort --zero-terminated --unique \
            )

  if [ "x$VERBOSE" != "xno" ]; then
    if [ "x$SOME_CONF_WAS_FOUND" = "xno" ]; then
      log_progress_msg "(omitted; missing conffile(s) in ${UWSGI_APPS_CONFDIR_GLOB})"
    elif [ "$ERRORS" -eq 0 ]; then
      log_progress_done
    fi
  fi

  return "$ERRORS"
}

do_with_given_specific_daemon()
{
  local COMMAND="$1"
  shift
  local RELATIVE_CONFPATH="$@"

  local ERRORS=0

  case "$COMMAND" in
    start)        do_start_specific_daemon "$RELATIVE_CONFPATH" ;;
    stop)         do_stop_specific_daemon "$RELATIVE_CONFPATH" ;;
    force-reload) do_force_reload_specific_daemon "$RELATIVE_CONFPATH" ;;
    reload|*)     do_reload_specific_daemon "$RELATIVE_CONFPATH" ;;
  esac
  case "$?" in
    0) log_progress_ok "$RELATIVE_CONFPATH" ;;
    1) log_progress_skip "$RELATIVE_CONFPATH" ;;
    *) log_progress_error "$RELATIVE_CONFPATH"
       ERRORS=1
    ;;
  esac

  return "$ERRORS"
}

# Print progress notification about successful command execution.
log_progress_ok()
{
  local RELATIVE_CONFPATH="$@"
  local CONFNAME=""

  [ "x$VERBOSE" = "xno" ] && return

  if [ "x$PRINT_CONFNAMES_IN_INITD_SCRIPT_OUTPUT" != "xno" ]; then
    CONFNAME="$(make_confname_for_progress_log "$RELATIVE_CONFPATH")"
    log_progress_msg "$CONFNAME"
  else
    log_progress_msg '.'
  fi
}

# Print progress notification about skipped command execution.
#
# It is printed, for example, when 'start' command was issued, but specific
# daemon is already started. Or when 'stop' command was issued, but specific
# daemon isn't runned yet.
log_progress_skip()
{
  local RELATIVE_CONFPATH="$@"
  local CONFNAME=""

  [ "x$VERBOSE" = "xno" ] && return

  if [ "x$PRINT_CONFNAMES_IN_INITD_SCRIPT_OUTPUT" != "xno" ]; then
    CONFNAME="$(make_confname_for_progress_log "$RELATIVE_CONFPATH")"
    log_progress_msg "(${CONFNAME})"
  else
    log_progress_msg "."
  fi
}

# Print progress notification about missing configuration file with given
# name.
log_progress_not_found()
{
  local RELATIVE_CONFPATH="$@"
  local CONFNAME=""

  [ "x$VERBOSE" = "xno" ] && return

  if [ "x$PRINT_CONFNAMES_IN_INITD_SCRIPT_OUTPUT" != "xno" ]; then
    CONFNAME="$(make_confname_for_progress_log "$RELATIVE_CONFPATH")"
  fi

  log_progress_msg "${CONFNAME}?"
}

# Print progress notification about failed command execution.
log_progress_error()
{
  local RELATIVE_CONFPATH="$@"
  local CONFNAME=""

  [ "x$VERBOSE" = "xno" ] && return

  if [ "x$PRINT_CONFNAMES_IN_INITD_SCRIPT_OUTPUT" != "xno" ]; then
    CONFNAME="$(make_confname_for_progress_log "$RELATIVE_CONFPATH")"
  fi

  log_progress_msg "${CONFNAME}!"
}

log_progress_done()
{
  log_progress_msg "done"
}

make_confname_for_progress_log()
{
  local RELATIVE_CONFPATH="$@"
  local CONFNAMESPACE="$(extract_confnamespace "$RELATIVE_CONFPATH")"
  local CONFNAME="$(extract_confname "$RELATIVE_CONFPATH")"

  echo "$(sanitize_confname "${CONFNAMESPACE}/${CONFNAME}")"
}

# Sanitize configuration file name for printing it in terminal.
sanitize_confname()
{
  local CONFNAME="$@"

  # In sanitizing:
  # * all control ASCII characters are replaced with '?' character
  # * confname with spaces is surrounded by single quotes.
  CONFNAME="$(echo -n "$CONFNAME" | tr '[\001-\037\177]' '?')"
  case "$CONFNAME" in
    *[[:space:]]*) echo "'$CONFNAME'" ;;
    *)             echo "$CONFNAME"   ;;
  esac
}

然后我重新启动了 uWSGI:

sudo service uwsgi restart

Django 应用程序正常启动。

答案3

首先,让配置更易于阅读,忘记上游的东西。我使用 uWSGI 已经很长时间了。我经常遇到套接字方面的问题(特别是在 Python 项目上),但使用 PHP 和 uWSGI 时,我能够很好地处理套接字。

如果你真的坚持使用 uWSGI,你需要两样东西!

第一个 config.ini,其中存储了与您的项目相关的所有 uWSGI 参数和 nginx 配置。

第二,nginx.conf,请求被路由回uWSGI进行进一步处理。

在 /etc/hosts 中:

127.0.0.1 projekte.local

nginx.conf:

server {
   listen 127.0.0.1:80;

   server_name projekte.local;
   include uwsgi_params;

   location / {
     uwsgi_pass 127.0.0.1:3030;
   }

projekte.conf(我们的 ini 文件):

[uwsgi]
socket = 127.0.0.1:3030    
uid = daemon
gid = daemon

venv = /storage/PyENV/projekteENV
project_dir = /storage/PyProjects/bprojekte/projekte
chdir = %(project_dir)
master = true
plugins = plugins/python/python    

check-static = %(project_dir)
static-skip-ext = .py
static-skip-ext = .pyc
static-skip-ext = .inc
static-skip-ext = .tpl

pidfile2 = /var/run/uwsgi/projekte.pid
disable-logging = false
processes = 8
cheaper = 2
#daemonize2 = true

enable-threads = true
offload-threads = N
py-autoreload = 1
wsgi-file = /storage/PyProjects/bprojekte/projekte/wsgi.py

你切换到 uWSGI 应用程序文件夹并使用以下命令启动 uWSGI:

./uwsgi --ini /path/to/projekte.conf

启动nginx:

/usr/local/nginx/sbin/nginx

并打开 URL(此例中为:http://projekte.local

问题:为什么你坚持使用 uWSGI? gunicorn 对于独立机器来说已经足够好了,而且使用起来更简单。从 gunicorn 切换到 uWSGI 只需一分钟(无需更改一行代码)。

uWSGI 用于扩展...用于独立...嗯,我不知道。

最好的,驯兽师

答案4

所以基本上,我的是一个 Django 项目。重置 root 密码后,我重新激活了虚拟环境并重新启动了 Nginx 和 Gunicorn。这解决了我的错误。

Nginx 重启:sudo service nginx restart
Gunicorn 重启:gunicorn --reload <your-wsgi-folder-name>.wsgi bind 0.0.0.0:8000

相关内容