webentwicklung-frage-antwort-db.com.de

uWSGI arbeitet als Prozess, aber nicht als Daemon

Für meine aktuelle Kolbenbereitstellung musste ich einen uwsgi-Server einrichten. So habe ich den uwsgi-Daemon erstellt:

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

Nachdem dies jedoch erfolgreich ausgeführt wurde: Sudo start uwsgi

uwsgi start/running, process 1286

Und versuchen, über einen Browser auf die Anwendung zuzugreifen:

Ich bekomme ein 502 Bad Gateway

und ein Fehlereintrag in nginx error.log:

2013/06/13 23:47:28 [Fehler] 743 # 0: * 296 Upstream vorzeitig geschlossene Verbindung beim Lesen des Antwortheaders vom Upstream, Client: xx.161.xx.228, Server: myproject.com, Anforderung: "GET/show_records/2013/6 HTTP/1.1 ", Upstream:" uwsgi: // unix: ///tmp/uwsgi.sock: ", Host:" myproject.com "

Die Socken-Datei verfügt jedoch über die erforderliche Berechtigung:

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

Wenn ich den Befehl exec von oben in der Befehlszeile als Prozess ausführe, funktioniert er einwandfrei. Warum funktioniert der Daemon bitte nicht richtig?

btw Nginx läuft als vim /etc/nginx/nginx.conf

user www-data;

und vim /etc/nginx/sites-available/default

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

und es wird als Sudo service nginx start gestartet

Ich führe dies auf Ubuntu 12.04 LTS aus.

Ich hoffe ich habe alle notwendigen Daten zur Verfügung gestellt, hoffe jemand kann mich in die richtige Richtung leiten. Vielen Dank.

15
Houman

Endlich habe ich dieses Problem gelöst, nachdem ich fast 2 Tage daran gearbeitet habe. Ich hoffe, diese Lösung hilft anderen Benutzern von flask/uwsgi, bei denen ein ähnliches Problem auftritt.

Ich hatte zwei Hauptprobleme, die dies verursachten.

1) Der beste Weg, um die Probleme mit einem Daemon zu finden, ist offensichtlich eine Protokolldatei und eine sauberere Struktur.

Sudo vim /etc/init/uwsgi.conf

Ändern Sie das Daemon-Skript wie folgt:

# 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

Dies ist eine viel sauberere Methode zum Einrichten des Daemons. Beachten Sie auch die letzte Zeile zum Einrichten der Protokolldatei. Anfangs hatte ich die Protokolldatei auf /var/log/uwsgi/error.log gesetzt. Nach viel Schweiß und Tränen stellte ich fest, dass der Dämon als www-data ausgeführt wird und daher nicht auf den /var/log/uwsgi/error.log zugreifen kann, da das error.log im Besitz von root:root war. Dies führte dazu, dass die UWSGI lautlos ausfiel.

Ich fand es viel effizienter, die Protokolldatei einfach auf meinen eigenen /myproject zu verweisen, auf den der Dämon als www-data garantierten Zugriff hat. Und vergessen Sie auch nicht, das gesamte Projekt für www-data zugänglich zu machen, sonst schlägt der Dämon mit einem Internal Server error message fehl. ->

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

Uwsgi daemon neu starten:

Sudo service uwsgi restart

2) Nun müssen Sie drei Protokolldateien suchen:

  • tail -f /var/log/upstart/uwsgi.log -> Zeigt beim Start Probleme mit Ihrem Daemon an

  • tail -f /var/log/nginx/error.log -> Zeigt Berechtigungsprobleme an, wenn der Zugriff auf wsgi verweigert wird, häufig, weil die /tmp/uwsgi.sock-Datei root anstelle von www-data gehört. In diesem Fall löschen Sie einfach die Socken-Datei Sudo rm /tmp/uwsgi.sock

  • tail -f /myproject/error.log -> Zeigt Fehler an, die von uwsgi in Ihrer Anwendung ausgelöst wurden

Diese Kombination von Protokolldateien half mir herauszufinden, dass ich auch einen schlechten Import mit Flask-Babel in meiner Flask-Anwendung hatte. In diesem Sinne ist es schlecht, dass ich bei der Verwendung der Bibliothek auf das Gebietsschema des Systems zurückgegriffen habe, um das datetime-Format zu bestimmen.

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'

So habe ich den Kolbenfilter verwendet:

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))

Das Seltsamste ist, dass dieser Code in der Entwicklungsumgebung (!) Einwandfrei funktioniert. Es funktioniert sogar einwandfrei, wenn uwsgi als Root-Prozess über die Befehlszeile ausgeführt wird. Es schlägt jedoch fehl, wenn es vom www-data-Daemon ausgeführt wird. Dies muss etwas damit zu tun haben, wie das Gebietsschema festgelegt ist, auf das Flask-Babel zurückzugreifen versucht.

Als ich den Import so änderte, funktionierte alles endlich mit dem Daemon:

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))

Seien Sie daher vorsichtig, wenn Sie Eclipse/Aptana Studio verwenden, das versucht, den richtigen Namespace für Ihre Klassen im Code auszuwählen. Es kann wirklich hässlich werden.

Es funktioniert nun seit 2 Tagen einwandfrei als uwsgi-Daemon auf einem Amazon Ec2 (Ubuntu 12.04). Ich hoffe, diese Erfahrung hilft anderen Python-Entwicklern.

19
Houman

Ich gab auf, es wurde kein uwsgi.log generiert und nginx beschwerte sich immer wieder über:

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"

für jede einzelne Anfrage. Dies geschah nur, wenn uwsgi als Dienst ausgeführt wurde. Als Prozess startete es problemlos unter einem beliebigen Benutzer. Das würde also von der Kommandozeile aus funktionieren (Seite antwortet):

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

Dies ist nicht gelungen (/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

Der Prozess würde beginnen, aber bei jeder Anfrage würde sich nginx über die geschlossene Verbindung beschweren. Seltsamerweise habe ich die gleiche Konfiguration für 2 andere Apps, die dieselbe Nginx-Version und dieselbe UWSGI-Version verwenden. Beide Apps sind Mezzanine-CMS-Apps. Ich versuchte alles, was mir einfiel und was vorgeschlagen wurde. Am Ende bin ich auf Gunicorn umgestiegen, was gut funktioniert:

#!/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

Und hier ist der, der nicht als Dienst funktionieren würde (Nginx beklagt sich über vorzeitig geschlossene Verbindung und keine App-Protokolldaten, die durchkommen).

#!/bin/bash

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

Und die 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

Ich bin letztes Jahr von Gunicorn zu UWSGI gewechselt und hatte bis jetzt keine Probleme damit, es schien auch ein bisschen schneller zu sein als Gunicorn. Im Moment denke ich daran, mich an Gunicorn zu halten. Es wird besser, bringt viel bessere Zahlen mit installiertem Eventlet und ist einfacher zu konfigurieren.

Hoffe, diese Problemumgehung hilft. Ich würde immer noch gerne das Problem mit uWSGI und Nginx kennen, aber ich bin ratlos.

Update: Die Verwendung von Gunicorn ermöglichte es mir, den Server als Dienst auszuführen, und während ich im Zwischengeschoss spielte, trat der folgende Fehler auf: FileSystemEncodingChanged

Um dies zu beheben, habe ich die Lösung hier gefunden: https://groups.google.com/forum/#!msg/mezzanine-users/bdln_Y99zQw/9HrhNSKFyZsJ

Und ich musste es etwas modifizieren, da ich kein Supervisord verwende, sondern nur Upstart und ein Shell-Skript. Ich habe dies hinzugefügt, bevor ich gunicorn in meiner Datei mez_server.sh ausführe:

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

Ich habe dieses Update auch mit uWSGI ausprobiert (viel kürzer als mit 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

Ich halte mich immer noch an Gunicorn, da es immer noch mit dem Problem zusammengearbeitet hat, und führe mich in die richtige Richtung, um es zu lösen. Ich war sehr enttäuscht, dass uWSGI auch mit diesen Parametern keine Ausgabe in der Protokolldatei lieferte. Ich habe nur den Startvorgang des Servers gesehen und das war's:

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

Während Nginx den Verbindungsabbruch-Fehler auslöste, saß uWSGI da, als ob nichts passieren würde.

0
radtek