[PYTHON] Verwenden der Flasche mit Nginx + Gunicorn-Konfiguration [Lokale Umgebung]

Zusammenfassung dieses Artikels

Flask_Nginx_unicorn_diagramdrawio-Step1-Server (1).png

Artikel-Kurzreferenztabelle

――Wenn Sie einen ähnlichen Artikel lesen, warum oft? Was meinst du? Ich fühle-> [Was ist / was ist ○○? ](Was bedeutet)

Versuche dich zu bewegen

Lassen Sie uns zunächst mit der obigen Konfiguration arbeiten. Installieren Sie die erforderlichen Pakete.

brew install nginx
pip install gunicorn

Projektstruktur und Inhalt jeder Datei

PROJECT
├── config
│   ├── gunicorn_settings.py #Anwendungsserver-Konfigurationsdatei
│   └── nginx.conf           #Webserver-Konfigurationsdatei
└── flask_app.py             #Hauptanwendung

flask_app.py


from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Index Page!'

@app.route('/health')
def health():
    return 'Health Check OK!!'

--Webserver-Konfigurationsdatei

gunicorn_settings.py


import os

bind = '127.0.0.1:' + str(os.getenv('PORT', 9876))
proc_name = 'Infrastructure-Practice-Flask'
workers = 1

--Nginx-Konfigurationsdatei

nginx.conf


#Weitere Informationen finden Sie im Abschnitt Konfigurationsdatei
worker_processes  1;

events {
	worker_connections 512;
}

http {
    server {
    	listen  9123;
    	server_name INFRA-PRACTICE-NGINX;
		charset UTF-8;

		proxy_set_header    Host    $host;

    	location / {
        	proxy_pass http://127.0.0.1:9876;
    	}

	    location /health/ {
        	proxy_pass http://127.0.0.1:9876/health;
    	}
    }
}

Starten Sie den Prozess

Terminal


#Starten Sie den Webserver
nginx -c ${PROJECT_PATH}/config/nginx.conf

#Starten Sie den Anwendungsserver
gunicorn flask_app:app -c config/gunicorn_settings.py

Kommunikation bestätigen

Terminal


curl http://localhost:9123/
# -> Index Page!OK, wenn es zurückkehrt
curl http://localhost:9123/health/
# -> Health Check OK!!OK, wenn es zurückkehrt

Entwirren Sie die Einstellungsdatei und die Start- / Endbefehle

gunicorn

Einstellungsdatei

In den offiziellen Dokumenten wird es in einem optionalen Format beschrieben. Wenn eine Einstellungsdatei verwendet wird, wird sie im Format "key = value" mit dem Namen des Einstellungselements als Schlüssel geschrieben (* z. B. "loglevel =" debug "). Die Erweiterung der Einstellungsdatei ist beliebig. Einige der Einstellungen sind unten aufgeführt.

key Bedeutung Schimmel        Standardwert
reload Bei Codeänderungen automatisch neu lesen und neu starten bool False
accesslog Zugriff auf das Protokollausgabeziel auf den Server
Geben Sie die Datei "-Bedeutet Standardausgabe
e.g. accesslog = logs/gunicorn_access.log
string None
errorlog Fehlerprotokollausgabeziel
Geben Sie die Datei "-Bedeutet Standardausgabe
e.g. errorlog = logs/gunicorn_err.log
string '-'
proc_name Prozessname, der vom Befehl ps angezeigt wird
Standard, sofern nicht anders angegeben_proc_Es wird der Name "Gunicorn"
string None
limit_request_line Maximale Größe der Anforderung, angegeben durch DDos-Maßnahmen
Beschränken Sie sich auf ähnliche Artikel_request_fields
int 4094
bind Verbindungshost und Port
HOST:Angegeben im PORT-Format
e.g. bind = os.getenv('HOST') + ':' + os.getenv('PORT')
string 127.0.0.1:8000
daemon Starten Sie den Gunicorn-Prozess als Daemon bool False
workers Anzahl der Worker-Prozesse, die Anforderungen bearbeiten
Ein übergeordneter Prozess wird gestartet, und es werden so viele untergeordnete Prozesse eingerichtet, wie Mitarbeiter vorhanden sind.
Die Angabe von 2 oder mehr, wenn Parallelität nicht berücksichtigt werden kann, führt zu einem Problem.
int 1
worker_connections Maximale Anzahl von Verbindungen int 1000

Befehl Start / Ende

【Anlaufen】

Terminal


gunicorn {Name der Kolbenanwendungsdatei}:{Name der Flask-Instanzvariablen in der Datei} -c {Pfad der Konfigurationsdatei}

[Ende] Strg + C im Terminal, in dem der Prozess ausgeführt wird

Nginx

Einstellungsdatei

Betrachtet man die offiziellen Dokumente, im Gegensatz zum Format "key = value" von gunicorn, Sie können sehen, dass die Direktive (Anweisung) im Kontextformat (* geschweifte Klammer: * Block in {}) innerhalb des Moduls beschrieben ist.

Module

Modulname Inhalt zu beschreiben
core Protokoll, Prozesssteuerung
Dies ist der äußerste Kontext
events Ereignisverarbeitung
http Verarbeitung in Bezug auf den Webserver
Wahrscheinlich das am meisten beschriebene Modul

Directive Syntax in http context Serverkontext im http-Kontext, weiterer Standortkontext im Serverkontext Und so weiter schreiben wir im Kontext im Kontextformat. Hier ist ein Beispiel für das Setzen des http-Blocks. Anhand des Beispiels können Sie verstehen, was die Einstellungsdatei am Anfang bedeutet.

--Grundeinstellungen

config


http {
    server {
        listen        80;                          #Warten Sie auf die Verbindung an Port 80
        server_name   MY_SERVER;                   #Der Servername ist MEIN_SERVER
        charset       UTF-8;                       #Antwortheader Inhalt-Geben Sie UTF ein-Bezeichnet als 8
        error_page    404  /404_not_found.html;    #404, wenn der Statuscode 404 ist_not_found.Interne Weiterleitung zu HTML
    }
}

--Reverse Proxy

config


http {
    server {
        # /Zugriff auf den Index
        location /index {
            proxy_pass          http://127.0.0.1:8080;  # 127.0.0.Proxy auf Port 1 8080 umkehren
            proxy_set_header    Host    $host;          #Von den an den Proxyserver übergebenen Anforderungsheadern Host$Host zurücksetzen
        proxy_read_timeout  60s;                    #Zeitüberschreitung, wenn 60 Sekunden lang keine Antwort vom Proxyserver erfolgt
        }
    }
}

config


config
http {
    server {
        location / {
            allow 192.168.0.1;    # 192.168.0.Zugriff von 1 zulassen
            deny  all;            #Verweigern Sie jeden anderen Netzwerkzugriff
        }
    }
}

config


http {
    server {
        location / {
            auth_basic             "Basic Auth closed site";  #Stellen Sie klar, dass eine BASIC-Authentifizierung erforderlich ist
            auth_basic_user_file   conf/htpasswd;               # .htpasswd Geben Sie den Dateipfad an
        }
    }
}

config


http {
    server {
        #Der Anforderungsheader enthält keinen Referer(none), In der Kopfzeile aber http://Oder https://Beginnt nicht mit(blocked)、
        # mintak.Endet nicht mit com(server_names)Wird beim Zugriff von der Wurzel aus als ungültig beurteilt->$invalid_Setzen Sie den Referer auf 1
        valid_referers none blocked server_names *mintak.com
        if ($invalid_referer) {
           return 403;  #Wenn festgestellt wird, dass es ungültig ist, wird es mit 403 Forbidden zurückgegeben.
        }
    }
}

Embbed Variable So etwas wie eine Umgebungsvariable auf einem Nginx-Server. Weitere Informationen finden Sie hier (https://nginx.org/en/docs/http/ngx_http_core_module.html#variables). Einige sind unten gezeigt.

variable Inhalt
$host Host im Anforderungsheader, Servername, falls nicht
$remote_addr Verbindungsclientadresse
$remote_port Verbundener Client-Port
$status Antwortstatus
$server_name Servername
$http_name Stellen Sie den Namen des Headerfelds im HTTP-Anforderungsheaderfeld und den Namensteil mit Unterstrich auf eine niedrigere Punktzahl ein
e.g. http_host、http_referer

Start / End-Befehl

【Anlaufen】

Terminal


nginx -c {Pfad der Konfigurationsdatei}

[Ende]

Terminal


nginx -s stop

#Wenn dies fehlschlägt, identifizieren Sie den Prozess und beenden Sie ihn
ps ax | grep nginx
kill -9 ${PID}

[Startbestätigung]

Terminal


ps aux | grep nginx    #Hier Nginx:Wenn Master-Prozess angezeigt wird, wird Nginx ausgeführt.

#Befehl, der PORT bestätigen kann
lsof -i -P | grep nginx
#=> nginx     41845 mintak    6u  IPv4 0x595e7f947462ada5      0t0  TCP *:9123 (LISTEN)

Was ist ○○?

Sie können den Zweck erreichen, indem Sie die Dateien bis zu diesem Punkt vorbereiten und den Befehl drücken. Es gibt jedoch viele schwierige Wörter und Konzepte für Anfänger wie mich. Von hier aus werde ich meine eigene Interpretation solcher Schlüsselwörter beschreiben.

Warum ist es so eine Konfiguration

Laut einem Experten wurden der Webserver und der Anwendungsserver in der Vergangenheit nicht getrennt. Diese Konfiguration wurde zu einem Problem, als wir uns der Tatsache stellten, dass mit der Verbreitung des Internets die Anzahl der Zugriffe auf öffentlich zugängliche Dienste zunahm, was die Belastung des Servers erhöhte und die Gesamtleistung verringerte. tat. Um einen stabilen Betrieb durch Verteilung der Last zu erreichen, muss der Server daher nach der später beschriebenen Rolle aufgeteilt werden. Diese Idee ist in der heutigen Zeit weit verbreitet, und es scheint, dass Webdienste im Allgemeinen aus einer dreischichtigen Struktur von "Webserver <-> Anwendungsserver <-> DB-Server" bestehen. Ich denke, dass die Grundidee der ** Trennung von Prozessen (Servern) für jede Rolle ** etwas mit dem Entwurfskonzept für die Codierung gemeinsam hat (eine klare Rolle für jede Klasse / Funktion).

Aber es funktioniert mit python flask_app.run

Dies liegt daran, dass das Framework namens Flask ein Framework ist, das gestartet werden kann, während es gleichzeitig als Webserver / Anwendungsserver dient. Dies ist nützlich, wenn es schwierig ist, den Webserver und den Anwendungsserver getrennt einzurichten, z. B. ** zur einfachen Überprüfung und Funktionsprüfung während der Entwicklung **. Wenn Sie mit diesem Befehl beginnen, wird das Protokoll "WARNUNG: Dies ist ein Entwicklungsserver. Verwendet es nicht in einer Produktionsentwicklung."] [^ 1] angezeigt, es ist jedoch nur für die Entwicklung und mit dieser Konfiguration für den Massenzugriff vorgesehen Dies bedeutet, dass während der Verarbeitung ein großes Pannenrisiko besteht. ** Produktionsstopp **.

Die Hauptrolle des Webservers und des Anwendungsservers

Ich werde jedes in einem Wort zusammenfassen. Weitere Informationen finden Sie auf der Referenzlink-Seite.

--Webserver: Unterstützt Anforderungen, die sich nicht ändern, unabhängig davon, wer auf sie zugreift (statische Verarbeitung). Die TOP-Seite ist leicht zu erreichen. --Application Server: Unterstützt Antworten, die sich je nach Zugriff ändern (dynamische Verarbeitung). Mitglied Meine Seite usw. (Der Inhalt der Anzeige ist je nach Mitglied unterschiedlich.)

Warum ist ein Reverse-Proxy umgekehrt?

Wenn es eine Rückwärtsfahrt gibt, gibt es eine Vorwärtsbewegung **. Was wir normalerweise als Proxy bezeichnen, ist ein Forward-Proxy.

Was ist der Unterschied zwischen einem Forward-Proxy und einem Reverse-Proxy?

Sie sind immer noch Stellvertreter zueinander. Die Verarbeitung zwischen Client-> Internet ist Forward-Proxy (Server) und die Verarbeitung zwischen Internet-> Ziel-Webserver ist Reverse-Proxy (Server). [^ 2]

Flask_Nginx_unicorn_diagramdrawio-Step1-Porxy.png

Sie müssen sich nur direkt mit dem Zielserver verbinden! Sie denken vielleicht, aber Sie können davon profitieren, den Proxyserver zu beißen (siehe unten).

Verwendung des Forward-Proxys

Verwenden Einzelheiten
Arbeitsersparnis Durch vorübergehendes Zwischenspeichern der Daten der Site, auf die einmal zugegriffen wurde, kann die Zeit bis zur Datenerfassung verkürzt werden, um Daten aus dem Cache abzurufen, ohne für den zweiten und nachfolgende Zugriff auf das Web zuzugreifen.
Inhaltsfilterung Blockieren Sie hier den Zugriff auf bestimmte Websites.
~~Es liegt hauptsächlich an diesem Typen, dass Sie diese Site auf Ihrem Firmen-PC nicht sehen können~~

Verwendung von Reverse Proxy

Verwenden Einzelheiten
Verbesserte Sicherheit Spezifische Zugriffsmethode(http://、https://Eine solche)ではない場合や特定のIPアドレス以外からのアクセスを遮断するEine solcheの機構を持たせることが出来る。
Lastverteilung(Lastenausgleicher) Einmal gepolstert, verteilt es den Zugriff erfolgreich auf mehrere Anwendungsserver.
Beschleunigen Statische Ausbeutung. Es ist möglich, die Belastung des Servers zu verringern und eine schnellere Antwort zurückzugeben, indem der Referenzinhalt wie Bilder und HTML-Dateien im Cache gehalten wird.

Was ist WSGI?

Abkürzung für Web Server Gateway Interface. ~~ Bekannt als Uesugi-Kun. ~~ Django und Flask sind WSGI-kompatible Frameworks, und gunicorn und uWEGI sind WSGI-kompatible Server. Ich denke, es gibt kein Problem mit der Erkennung. Der Hintergrund seines Aussehens ist wie folgt. [^ 3]

・ Framework A-chan> Ich bin cool, also bin ich verrückt, außer α-kun, einem coolen Webserver ・ Framework B> Ich mag ein festes β-Kun ♡

In der Vergangenheit waren die Webserver, die für jedes Python-Webframework verwendet werden können, begrenzt (und umgekehrt). Eigentlich wollte ich, dass B-chan α-kun verwendet, aber hier ist die eheähnliche Beziehung zu A-chan ein Nachteil. Es waren ~~ Uesugi-kun und ~~ WEGI, die dieses Problem zu lösen schienen. WEGI sagt: "Lassen Sie uns frei für den Server und das Framework wählen ~~ love ~~ Let's connect", wie man in der Beziehung des Anwendungsframeworks <-> Webserver interagiert Ich habe die Regel festgelegt. Dank WSGI- und WSGI-kompatiblen Servern und Frameworks können wir jetzt die Kombination aus Server und Framework frei wählen. Ich bin glücklich.

References

[^ 1]: Wenn "FLASK_ENV = Entwicklung" nicht gesetzt ist. [^ 2]: Dieses Mal ist Nginx sowohl ein Proxyserver als auch ein Webserver. [^ 3]: Ich denke, das ist der einzige Weg, um diese dumme Sache zu erklären. .. ..

Recommended Posts

Verwenden der Flasche mit Nginx + Gunicorn-Konfiguration [Lokale Umgebung]
[Mit Bilddiagramm] Nginx + Gunicorn + Flask konvertiert zu Docker [Teil 2]
[Mit Bilddiagramm] Nginx + Gunicorn + Flask konvertiert zu Docker [Teil 1]
Verwenden von Chainer mit CentOS7 [Umgebungskonstruktion]
Webanwendung mit Python + Flask (unter Verwendung von VScode) # 1 - Aufbau einer virtuellen Umgebung-
Erstellen Sie mit pyenv unter Ubuntu 12.04 schnell eine Ausführungsumgebung für Python3.4 + Nginx + uWSGI + Flask-Webanwendungen
Wettbewerbsprogrammierung mit Python Lokale Umgebungseinstellungen
Code-Server Lokale Umgebung (3) Verwenden Sie das VSCode-Plugin
Stellen Sie die Kolben-App mit mod_wsgi bereit (mithilfe von pipenv).
Vue.js + Konstruktionsmemorandum zur Flaschenumgebung ~ mit Anaconda3 ~
Holen Sie sich mit Docker eine lokale Umgebung für DynamoDB
Erstellen Sie mit Docker eine Python + uWSGI + Nginx-Umgebung
Zusammenfassung der Nginx-Einstellungen (Flask + Docker + Gunicorn Edition)
Erstellen Sie mit Docker eine Umgebung aus NGINX + NGINX Unit + MySQL
Flasche + Gunicorn + Nginx + Supervisor Bis es funktioniert
Erstellen Sie mit venv unter Ubuntu 14.04 LTS schnell eine Ausführungsumgebung für Python3.4 + Nginx + uWSGI + Flask-Webanwendungen
Konstruktionsvorlage für die lokale Python-Entwicklungsumgebung [Flask / Django / Jupyter mit Docker + VS-Code]
Konvertieren der Django-Umgebung in Docker (Docker + Django + Gunicorn + Nginx) Teil 2
Versuchen Sie, die virtuelle Umgebung von conda mit Jupyter Notebook zu verwenden
Erstellen Sie mit Docker eine Umgebung aus Nginx + uWSGI + Python (Django)
Senden Sie msgpack mit Ajax an die flk (werkzeug) Umgebung
Konvertieren der Django-Umgebung in Docker (Docker + Django + Gunicorn + Nginx) Teil 3
Aufbau einer virtuellen Umgebung mit Docker + Flask (Python) + Jupyter-Notebook
Erstellen Sie mit Python + Flask einen animierten lokalen GIF-Server
Full-Scale-Server mit Nginx + uWSGI + Flask + Ubuntu (Installation)
Ausgabeprotokoll an die Konsole mit Flask + Nginx auf Docker
[Python] Ich habe versucht, einen lokalen Server mit flask auszuführen
Full-Scale-Server mit Nginx + uWSGI + Flask + Ubuntu (Implementierung)
Erstellen Sie eine Django-Umgebung mit Docker-Compose (MariaDB + Nginx + uWSGI).