Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie Nginx + UWSGI

So verwenden Sie Nginx + UWSGI

巴扎黑
巴扎黑Original
2017-04-05 14:56:181458Durchsuche

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)

Servicestrategie

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.

Gunicorn (WSGI-Server für die Python-UNIX-Plattform)

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

uwsgi

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)

Kontinuierliche Iteration zum Erfolg

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

Füge sie zusammen

Ich mag es, Dinge zu tun, anstatt darüber zu reden, deshalb gebe ich Ihnen hier einige aktuelle Einstellungen unserer Online-Server.

nginx

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.

uwsgi

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[&#39;getsentry&#39;][&#39;web&#39;][&#39;threads&#39;]}"

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 &#39;%(program_name)s %(process_num)02d&#39;
  numprocs node[&#39;getsentry&#39;][&#39;web&#39;][&#39;processes&#39;]
end

Standortauswahl

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn