web-dev-qa-db-ja.com

uWSGIはプロセスとして機能しますが、デーモンとしては機能しません

現在のflaskデプロイメントでは、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を取得します

およびnginxerror.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で実行しています。

必要なデータをすべて提供したことを願っています。誰かが私を正しい方向に導いてくれることを願っています。ありがとう。

15
Houman

ついに私はこの問題に2日近く取り組んだ後、この問題を解決しました。このソリューションが、同様の問題を経験している他のフラスコ/ uwsgiユーザーに役立つことを願っています。

これを引き起こした2つの大きな問題がありました。

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として実行されているため、error.logが/var/log/uwsgi/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)これで、注意すべき3つのログファイルができました。

  • tail -f /var/log/upstart/uwsgi.log->起動時にデーモンの問題を表示します

  • tail -f /var/log/nginx/error.log-> /tmp/uwsgi.sockファイルがwww-dataではなくrootによって所有されていることが多いため、wsgiアクセスが拒否されたときにアクセス許可の問題を示します。その場合は、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を実行する場合でも、正常に機能します。ただし、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/AptanaStudioを使用する場合は注意が必要です。それは本当に醜くなる可能性があります。

2日間から、Amazon Ec2(Ubuntu 12.04)のuwsgiデーモンとして完全に正常に動作しています。この経験が仲間のpython開発者に役立つことを願っています。

19
Houman

私はあきらめました、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に固執することを考えています。それは良くなり、イベントレットがインストールされているとはるかに良い数字を出し、設定が簡単になります。

この回避策がお役に立てば幸いです。 uWSGIとnginxの問題を知りたいのですが、困惑しています。

更新:したがって、gunicornを使用すると、サーバーをサービスとして実行でき、メザニンをいじっているときに、次のエラーが発生しました:FileSystemEncodingChanged

これを修正するために、私はここで解決策を見つけました: https://groups.google.com/forum/#!msg/mezzanine-users/bdln_Y99zQw/9HrhNSKFyZsJ

また、supervisordを使用せず、upstartとシェルスクリプトのみを使用するため、少し変更する必要がありました。 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は何も起こらないようにそこに座っていました。

0
radtek