16

对于我当前的烧瓶部署,我必须设置一个 uwsgi 服务器。这就是我创建 uwsgi 守护进程的方式:

sudo vim /etc/init/uwsgi.conf

# file: /etc/init/uwsgi.conf
description "uWSGI server"

start on runlevel [2345]
stop on runlevel [!2345]
respawn

exec /myproject/myproject-env/bin/uwsgi --uid www-data --gid www-data --home /myproject/myproject-env/site/F11/Engineering/  --socket /tmp/uwsgi.sock --chmod-socket --module F11 --callable app --pythonpath /myproject/myproject-env/site/F11/Engineering/ -H /myproject/myproject-env

但是成功运行后:sudo start uwsgi

uwsgi start/running, process 1286

并尝试通过浏览器访问应用程序:

我得到一个502 Bad Gateway

以及 nginx error.log 中的错误条目:

2013/06/13 23:47:28 [错误] 743#0: *296 上游过早关闭连接,同时从上游读取响应标头,客户端:xx.161.xx.228,服务器:myproject.com,请求:“GET /show_records/2013/6 HTTP/1.1”,上游:“uwsgi://unix:///tmp/uwsgi.sock:”,主机:“myproject.com”

但是 sock 文件有它需要的权限:

srw-rw-rw- 1 www-data www-data 0 Jun 13 23:46 /tmp/uwsgi.sock

如果我exec在命令行中将上面的命令作为一个进程运行,它工作得非常好。请问为什么守护进程不能正常工作?

顺便说一句,Nginx 运行为 vim /etc/nginx/nginx.conf

user www-data;

vim /etc/nginx/sites-available/default

location / {
                uwsgi_pass   unix:///tmp/uwsgi.sock;
                include        uwsgi_params;
        }

它开始于sudo service nginx start

我正在运行这个Ubuntu 12.04 LTS

我希望我已经提供了所有必要的数据,希望有人能引导我走向正确的方向。谢谢。

4

3 回答 3

21

经过近2天的工作,我终于解决了这个问题。我希望这个解决方案能帮助遇到类似问题的其他烧瓶/uwsgi 用户。

我有两个主要问题导致了这种情况。

1) 发现守护进程问题的最佳方法显然是日志文件和更清晰的结构。

sudo vim /etc/init/uwsgi.conf

将守护程序脚本更改为以下内容:

# file: /etc/init/uwsgi.conf
description "uWSGI server"

start on runlevel [2345]
stop on runlevel [!2345]
respawn
exec /home/ubuntu/uwsgi-1.9.12/uwsgi -c /myproject/uwsgi.ini

vim /myproject/uwsgi.ini

[uwsgi]
socket = /tmp/uwsgi.sock
master = true
enable-threads = true
processes = 5
chdir= /myproject/F11/Engineering
module=F11:app
virtualenv = /myproject/myproject-env/
uid =  www-data
gid = www-data
logto = /myproject/error.log

这是设置守护程序的更简洁的方法。还要注意最后一行如何设置日志文件。最初我将日志文件设置为/var/log/uwsgi/error.log. 经过大量的汗水和泪水,我意识到守护程序正在运行www-data,因此无法访问,/var/log/uwsgi/error.log因为 error.log 归root:root. 这使得 uwsgi 静默失败。

我发现将日志文件指向我自己的日志文件更有效/myproject,其中守护进程保证访问为www-data. 并且不要忘记让整个项目都可以访问,www-data否则守护程序将失败并显示Internal Server error message. -->

sudo chown www-data:www-data -R /myproject/

重启 uwsgi 守护进程:

sudo service uwsgi restart

2) 现在您需要注意三个日志文件:

  • tail -f /var/log/upstart/uwsgi.log --> 在启动时显示你的守护进程的问题

  • tail -f /var/log/nginx/error.log --> 当 wsgi 访问被拒绝时显示权限问题,通常是因为/tmp/uwsgi.sock文件由root而不是www-data. 在这种情况下,只需删除 sock 文件sudo rm /tmp/uwsgi.sock

  • tail -f /myproject/error.log --> 显示 uwsgi 在你的应用程序中抛出的错误

这种日志文件组合帮助我发现我在 Flask 应用程序中也有一个错误的 Flask-Babel 导入。从这个意义上说不好,我使用库的方式是回退到系统的语言环境来确定日期时间格式。

File "/myproject/F11/Engineering/f11_app/templates/show_records.html", line 25, in block "body"
    <td>{{ record.record_date|format_date }}</td>
  File "./f11_app/filters.py", line 7, in format_date
    day = babel_dates.format_date(value, "EE")
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 459, in format_date
    return pattern.apply(date, locale)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 702, in apply
    return self % DateTimeFormat(datetime, locale)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 699, in __mod__
    return self.format % other
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 734, in __getitem__
    return self.format_weekday(char, num)
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 821, in format_weekday
    return get_day_names(width, context, self.locale)[weekday]
  File "/myproject/myproject-env/local/lib/python2.7/site-packages/babel/dates.py", line 69, in get_day_names
    return Locale.parse(locale).days[context][width]
AttributeError: 'NoneType' object has no attribute 'days'

这是我使用 Flask 过滤器的方式:

import babel.dates as babel_dates

@app.template_filter('format_date')
def format_date(value):
    day = babel_dates.format_date(value, "EE")
    return '{0} {1}'.format(day.upper(), affix(value.day))

最奇怪的是,这段代码在开发环境中运行良好(!)。从命令行将 uwsgi 作为 root 进程运行时,它甚至可以正常工作。但是当由 www-data 守护进程运行时它会失败。这一定与语言环境的设置方式有关,而 Flask-Babel 正试图回退到该语言环境。

当我像这样更改导入时,它最终与守护进程一起工作:

from flask.ext.babel import format_date  

@app.template_filter('format_date1')
def format_date1(value):
    day = format_date(value, "EE")
    return '{0} {1}'.format(day.upper(), affix(value.day))

因此,在使用 Eclipse/Aptana Studio 尝试为代码中的类选择正确的命名空间时要小心。它真的会变得丑陋。

自 2 天以来,它现在作为 Amazon Ec2(Ubuntu 12.04)上的 uwsgi 守护程序工作得非常好。我希望这个经验对 Python 开发者有帮助。

于 2013-06-16T22:14:40.133 回答
0

我放弃了,没有生成 uwsgi.log,nginx 一直在抱怨:

2014/03/06 01:06:28 [error] 23175#0: *22 upstream prematurely closed connection while reading response header from upstream, client: client.IP, server: my.server.IP, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:/var/web/the_gelatospot/uwsgi.sock:", host: "host.ip"

对于每一个请求。这只发生在将 uwsgi 作为服务运行时,作为一个进程,它在任何用户下都可以正常启动。所以这可以从命令行工作(页面响应):

$exec /var/web/the_gelatospot/mez_server.sh

这没有(/etc/init/site_service.conf):

description "mez sites virtualenv and uwsgi_django" start on runlevel
[2345] stop on runlevel [06] respawn respawn limit 10 5 exec
/var/web/the_gelatospot/mez_server.sh

该过程将开始,但在每个请求 nginx 都会抱怨关闭的连接。奇怪的是,对于使用相同 nginx 版本和相同 uwsgi 版本的其他 2 个应用程序,我有相同的配置工作得很好,而且这两个应用程序都是夹层 CMS 应用程序。我尝试了所有我能想到的和建议的。最后,我切换到了很好用的 gunicorn:

#!/bin/bash

NAME="the_gelatospot"                                          # Name of the application
DJANGODIR=/var/web/the_gelatospot              # Django project directory
SOCKFILE=/var/web/the_gelatospot/gunicorn.sock     # we will communicte using this unix socket
USER=ec2-user
GROUP=ec2-user                                             # the user to run as, the group to run as
NUM_WORKERS=3                                     # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=settings
#DJANGO_SETTINGS_MODULE=the_gelatospot.settings             # which settings file should Django use
#DJANGO_WSGI_MODULE=the_gelatospot.wsgi                   # WSGI module name
DJANGO_WSGI_MODULE=wsgi

echo "Starting $NAME as `the_gelatospot`"

# Activate the virtual environment
cd $DJANGODIR
source ../mez_env/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
cd ..
# Start your Django GUnicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec gunicorn -k eventlet ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --log-level=debug \
  --bind=unix:$SOCKFILE

这是一个不能作为服务工作的服务(nginx 抱怨连接过早关闭并且没有应用程序日志数据通过)。

#!/bin/bash

DJANGODIR=/var/web/the_gelatospot/                # Django project directory
cd $DJANGODIR
source ../mez_env/bin/activate
uwsgi --ini uwsgi.ini

和 uwsgi.ini:

[uwsgi]
uid = 222
gid = 500
socket = /var/web/the_gelatospot/uwsgi.sock
virtualenv = /var/web/mez_env
chdir = /var/web/the_gelatospot/
wsgi-file = /var/web/the_gelatospot/wsgi.py
pythonpath = ..
env = DJANGO_SETTINGS_MODULE=the_gelatospot.settings
die-on-term = true
master = true
chmod-socket = 666
;experiment using uwsgitop
worker = 1
;gevent = 100
processes = 1
daemonize = /var/log/nginx/uwsgi.log
logto = /var/log/nginx/uwsgi.logi
log-maxsize = 10000000
enable-threads = true

去年我从 gunicorn 转到了 uWSGI,直到现在我都没有遇到任何问题,它似乎也比 gunicorn 快一点。现在我正在考虑坚持gunicorn。它变得越来越好,安装了 eventlet 后提供了更好的数字,并且更易于配置。

希望此解决方法有所帮助。我仍然想知道 uWSGI 和 nginx 的问题,但我很难过。

更新: 所以使用 gunicorn 允许我将服务器作为服务运行,并且在玩夹层时我遇到了这个错误:FileSystemEncodingChanged

为了解决这个问题,我在这里找到了解决方案: https ://groups.google.com/forum/#!msg/mezzanine-users/bdln_Y99zQw/9HrhNSKFyZsJ

而且我不得不对其进行一些修改,因为我不使用supervisord,我只使用upstart 和一个shell 脚本。我在我的 mez_server.sh 文件中执行 gunicorn 之前添加了这个:

export LANG=en_US.UTF-8, LC_ALL=en_US.UTF-8, LC_LANG=en_US.UTF-8
exec gunicorn -k eventlet ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --log-level=debug \
  --bind=unix:$SOCKFILE

我也像这样使用 uWSGI 尝试了这个修复(比使用 uwsgi.ini 短很多):

export LANG=en_US.UTF-8, LC_ALL=en_US.UTF-8, LC_LANG=en_US.UTF-8
exec uwsgi --ini uwsgi.ini

我仍然坚持使用 gunicorn,因为它仍然可以解决问题并引导我朝着正确的方向解决问题。即使使用这些参数,uWSGI 也没有在日志文件中提供任何输出,我感到非常失望,我只看到了服务器启动过程,仅此而已:

daemonize = /var/log/nginx/uwsgi.log
logto = /var/log/nginx/uwsgi.logi

当 nginx 不断抛出断开连接错误时,uWSGI 就像什么都没发生一样坐在那里。

于 2014-03-06T02:05:08.387 回答
-1

作为使用 daemon true 命令运行的单行是

gunicorn  app.wsgi:application -b 127.0.0.1:8000 --daemon

将您的应用程序与 127.0.0.1:8000 绑定并 --deamon 强制它作为守护程序运行

但是定义一个 gunicorn_config.cfg 文件并使用 -c 标志运行是一个好习惯

更多:

https://gunicorn-docs.readthedocs.org/en/develop/configure.html

于 2016-01-05T12:25:09.660 回答