Nach vielen Experimenten (auf disqus.com und getsentry.com) kann ich definitiv sagen: uwsgi sollte der Standard in der Python-Welt werden. Kombinieren Sie es mit Nginx und Sie können ein besseres Leistungserlebnis für Threads (oder Nicht-Threads) in Python-basierten Webanwendungen erzielen.
Update: Ignorieren Sie das uralte Sprichwort „Jede Metrik, die Sie angeben, ist langsam“. Mit Anfragen meine ich hier die Backend-Knoten. Sie verarbeiten eingehende Ereignisse (Anfragen mit einer Größe von 20 KB bis 1 MB) und durchlaufen verschiedene Hops in der Netzwerkautorisierung und -quote Richtlinien, und die meisten bilden einige Warteschlangenoperationen. Entladen Sie so viel Arbeitslast wie möglich. (Es gibt ein Problem mit der Übersetzung dieses Absatzes, bitte beziehen Sie sich auf den Originaltext, Anmerkung des Übersetzers)
Es gibt bereits eine Reihe von Möglichkeiten, Python-Anwendungen auszuführen. Ich werde mod_wsgi nicht verwenden und vor allem versuche ich nicht zu erklären, wie das Ereignismodell funktioniert. Ich glaube nicht, dass sie in der Python-Welt noch verwendet werden, daher geht es in diesem Artikel nicht um traditionelle Python-Anwendungen mit Threads (oder Multiprozessen).
Stattdessen werde ich mich auf die beiden beliebtesten Lösungen konzentrieren, mit denen ich am besten vertraut bin: gunicorn und uwsgi.
Rückblickend war die Lösung für den Python-Webserver im Wesentlichen mod_wsgi. Eine der beliebtesten (oder als modernsten) Methoden ist in letzter Zeit Gunicorn.
Tatsächlich empfehle ich immer noch die Verwendung von Gunicorn, was die Unannehmlichkeiten erheblich reduziert: Es bettet Django wunderbar ein und ist einfach einzurichten.
Es verfügt außerdem über 10 % der gleichen Konfigurationsoptionen wie uwsgi (was für manche Leute eine gute Sache ist), aber ansonsten bietet es im Vergleich fast die gleichen Grundfunktionen wie uwsgi (oder jeder andere Python-Webserver).
Meiner Meinung nach ist dies die einzige Option, von Gunicorn bis uwsgi. Es wird eine höhere Leistung geben, mehr Konfigurationsoptionen, die leicht zu verstehen sind, und die Möglichkeit, über das Protokoll mit Nginx zu interagieren, bringt ebenfalls Vorteile mit sich.
Die Konfiguration ist ebenfalls recht einfach. Finden Sie einfach einen Artikel dazu, mehr dazu später.
Ich habe angefangen, uwsgi zum Ausführen einiger Anwendungen zu verwenden, und habe –processes=10 und –threads=10 verwendet, um die Multi-CPU des Servers zu testen. Es gab zwei Zwecke:
Unterstützen Sie
Testen Sie die Möglichkeit, die Speichernutzung zu reduzieren
Testen Sie die Thread-Sicherheitsunterstützung
(Was die Frage angeht, ob sich diese Tests lohnen: DISQUS läuft in einem einzelnen Thread. Ich möchte es so rational wie möglich halten und die Fähigkeiten jedes Knotens maximieren)
Wir haben die durchschnittliche API-Antwortzeit auf weniger als 40 ms reduziert, worauf ich sehr stolz bin. Die API-Antwortzeit, von der ich hier spreche, bezieht sich auf die Zeit, die von der Anfrage beim Python-Server bis zu dem Zeitpunkt vergeht, an dem der Server die Antwort an den Proxy zurückgibt.
Als wir immer mehr Datenverkehr bekamen und es zu Zugriffsspitzen kam, begann die Antwortzeit zu versagen. Die schwankenden Antwortzeiten entsprachen nicht mehr unseren ursprünglichen Erwartungen, obwohl wir immer noch etwa 30 % des Speichers auf dem Serviceknoten hatten und 60 % % der Ressourcen sind verfügbar.
Nach vielen Anpassungen haben wir eine große Anzahl von uwsgi-Prozessen deaktiviert und Nginx die Last ausgleichen lassen (zuvor ließen wir die Last von uwsgi selbst ausgleichen).
Das bedeutet, dass wir statt „uwsgi processing=10“ 10 separate uwsgi-Instanzen statt „--processes=10“ ausführen.
Das Ergebnis ist eine schöne, konsistente durchschnittliche Reaktionszeit von 20 ms.
API-Antwortzeit
Ich mag es, Dinge zu tun, anstatt darüber zu reden, deshalb gebe ich Ihnen hier einige aktuelle Einstellungen unserer Online-Server.
Der erste Teil der Konfiguration ist Nginx. Wir müssen die Anzahl der UWSGI-Prozess-Backends tatsächlich berechnen und hinzufügen, daher ist die Sache etwas kompliziert.
Wir erstellen zunächst eine Konfigurationsliste auf unserer Webseite:
# recipes/web.rb hosts = (0..(node[:getsentry][:web][:processes] - 1)).to_a.map do |x| port = 9000 + x "127.0.0.1:#{port}" end template "#{node['nginx']['dir']}/sites-available/getsentry.com" do source "nginx/getsentry.erb" owner "root" group "root" variables( :hosts => hosts ) mode 0644 notifies :reload, "service[nginx]" end
Die Konfiguration von Nginx ist sehr einfach:
# templates/getsentry.erb upstream internal { <% @hosts.each do |host| %> server <%= host %>; <% end %> } server { location / { uwsgi_pass internal; uwsgi_param Host $host; uwsgi_param X-Real-IP $remote_addr; uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for; uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto; include uwsgi_params; } }
Jetzt haben wir die Anzahl der uwsgi-Hosts festgelegt und Gewichtungswerte zugewiesen, beginnend mit Port 9000, den Socket-Adressen, die von der uwsgi-Konfiguration verwendet werden.
Andererseits verwenden wir Supervisor, um den UWSG-Prozess zu steuern, was ebenfalls sehr einfach ist:
# recipes/web.rb command = "/srv/www/getsentry.com/env/bin/uwsgi -s 127.0.0.1:90%(process_num)02d --need-app --disable-logging --wsgi-file getsentry/wsgi.py --processes 1 --threads #{node['getsentry']['web']['threads']}" supervisor_service "web" do directory "/srv/www/getsentry.com/current/" command command user "dcramer" stdout_logfile "syslog" stderr_logfile "syslog" startsecs 10 stopsignal "QUIT" stopasgroup true killasgroup true process_name '%(program_name)s %(process_num)02d' numprocs node['getsentry']['web']['processes'] end
Sofern nicht jemand ein sehr überzeugendes Argument dafür vorbringt, warum es einen anderen Weg geben sollte (oder etwas, das in diesem Fall nicht funktioniert), würde ich gerne etwas über dieses Muster hören, wenn die Python-Welt immer mehr zum Standard wird. Zumindest würde ich gerne den Anstoß zu einer Debatte darüber sehen, wie das Prozessmanagement innerhalb von uwsgi verbessert werden kann.
Das obige ist der detaillierte Inhalt vonSo verwenden Sie Nginx + UWSGI. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!