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