Kapitel "Paralleles Verarbeiten von Anfragen" wurde aktualisiert.
Wenn Sie mehr lesen möchten, "mögen" oder "folgen Sie mir" in Buch ;-)
Das Folgende ist ein Auszug aus dem Inhalt des Buches.
Python liest den Quellcode in der Reihenfolge von oben und führt nach Abschluss der Verarbeitung einer Zeile die nächste Zeile der Reihe nach aus.
Daher mit dem aktuellen Quellcode,
. Accept ()
)
--Handle Anfragen von Clients (.handle_client ()
)
-Endkommunikation mit dem Client (ggf. nach Behandlung von Ausnahmen) (.close ()
). Accept ()
)Befolgen Sie unbedingt diese Reihenfolge.
Mit anderen Worten, ** "Die nächste Anfrage wird erst akzeptiert, wenn die Bearbeitung einer Anfrage abgeschlossen ist" ** Es bedeutet das.
Dies wird zu einem großen Problem, wenn die Anzahl der Anforderungen zunimmt.
Angenommen, 10 Anfragen gehen gleichzeitig ein.
Zu diesem Zeitpunkt beginnt der Server mit der Verarbeitung der ersten Anforderung, die zuerst eintritt. Und wenn diese erste Anforderung ein sehr zeitaufwändiger Prozess ist, müssen die nächsten 9 Anforderungen warten, bis der Prozess abgeschlossen ist.
Ein häufiger Fall besteht darin, eine Abfrage mit komplexen Suchkriterien an einen DB-Server zu senden und 30 Sekunden auf eine Antwort zu warten. Die Gesamtleistung ist viel besser, wenn der Computer die anderen 9 Anforderungen 30 Sekunden lang verarbeitet und auf eine Antwort von der Datenbank wartet.
Auf diese Weise wird die Ausführung eines anderen Programms hinter den Kulissen, während ein bestimmtes Programm einen bestimmten Prozess ausführt, als ** Parallelverarbeitung ** oder ** Parallelverarbeitung ** bezeichnet.
Diese parallele Verarbeitung ist für allgemeine Webserver selbstverständlich, also implementieren wir sie auch.
Lassen Sie mich den Unterschied zwischen "Parallelverarbeitung" und "Parallelverarbeitung" erklären.
Im Allgemeinen wird die gleichzeitige Verarbeitung mehrerer Monogotos als "Parallelverarbeitung" bezeichnet.
In der Computerwelt ist die CPU für die gesamte eigentliche Verarbeitung verantwortlich, aber eine CPU kann immer nur einen Job gleichzeitig ausführen. Daher kann im engeren Sinne eine "Parallelverarbeitung" nicht mit einer CPU realisiert werden.
Aus menschlicher Sicht ist die CPU-Verarbeitung jedoch so schnell, dass "Wenn Sie diesen Job machen und" warten ", wechseln Sie zu einem anderen Job, und wenn Sie wieder" warten ", machen Sie einen anderen Job." ` Durch das Umschalten der zu behandelnden Prozesse nacheinander kann das menschliche Auge erkennen, dass sie gleichzeitig Aufgaben ausführen. (Je nach Betriebssystem wechselt die CPU die Jobs nacheinander in maximal 0,2 Sekunden.)
Früher war es für einen Computer selbstverständlich, eine CPU zu haben, daher gab es in der Computerwelt kein besonderes Problem, diese "pseudo-parallele Verarbeitung" einfach als "parallele Verarbeitung" zu lesen. Mit der Veröffentlichung / Verbreitung von Dual-Core-CPUs um das Jahr 2000 wurden jedoch zwei oder vier CPUs (genauer gesagt CPU-Kerne) auf einem Computer installiert, und durch gleichzeitigen Betrieb dieser CPUs wurde "Pseudo". Es ist möglich geworden, "echte Parallelverarbeitung" anstelle von "Parallelverarbeitung" durchzuführen.
Daher nennen Programmierer "pseudo-parallele Verarbeitung" "** parallele ** Verarbeitung", um zwischen "pseudo-paralleler Verarbeitung" und "echter paralleler Verarbeitung" zu unterscheiden, die zuvor als "parallele Verarbeitung" gelesen wurden. Es wurde.
Es ist für den Menschen äußerst schwierig, an der Oberfläche zwischen "Parallelverarbeitung" und "Parallelverarbeitung" zu unterscheiden, und es besteht fast keine Notwendigkeit, zwischen beiden in Bezug auf die Programmierung zu unterscheiden, bis eine Optimierung der Maschinenleistung erforderlich ist. Daher werden diese in diesem Dokument zusammenfassend als "Parallelverarbeitung" ohne besondere Unterscheidung bezeichnet.
Es ist eine sehr komplizierte Geschichte darüber, wann Parallelverarbeitung und Parallelverarbeitung richtig verwendet werden und wie sie sich auf die Leistung auswirken. Ich werde es in diesem Buch weglassen. Im Internet sind viele Informationen zu diesem Thema verfügbar. Wenn Sie also interessiert sind, lesen Sie sie durch.
Hier ist der verbesserte Quellcode für die Parallelverarbeitung. Bitte beachten Sie, dass es zwei Dateien gibt.
study/WebServer.py
https://github.com/bigen1925/introduction-to-web-application-with-python/blob/main/codes/chapter13/WebServer2.py
study/WorkerThread.py
https://github.com/bigen1925/introduction-to-web-application-with-python/blob/main/codes/chapter13/WebServer2.py
Common
Da die Dateien getrennt sind, werden die Zeichen "Server:" und "Worker:" in das Protokoll ausgegeben, in dem der Verarbeitungsdatensatz angezeigt wird. Beispiel)
print("=== Server:Starten Sie den Server===")
print("=== Worker:Beenden Sie die Kommunikation mit dem Kunden===")
WebServer.py
#Erstellen Sie einen Thread für den Client
thread = WorkerThread(client_socket)
#Thread ausführen
thread.start()
Erstellen Sie einen ** Thread **, um den Client zu verarbeiten, der die Verbindung hergestellt hat, und beginnen Sie mit der Verarbeitung des Threads.
Die Verarbeitung, die von der Methode .handle_client ()
bis zum letzten Mal durchgeführt wurde, und die Ausnahmeverarbeitung davor und danach wurden alle in die Verarbeitung in diesem Thread verschoben.
Ein ** Thread ** ist eine Verarbeitungssequenz, die es einem Computer ermöglicht, parallel zu verarbeiten, was später ausführlich erläutert wird.
WorkerThread.py
class WorkerThread(Thread):
#Verzeichnis mit ausführbaren Dateien
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#Verzeichnis zum Speichern statisch zu liefernder Dateien
DOCUMENT_ROOT = os.path.join(BASE_DIR, "static")
def __init__(self, client_socket: socket):
super().__init__()
self.client_socket = client_socket
def run(self) -> None:
"""
Empfängt einen mit dem Client verbundenen Socket als Argument
Verarbeiten Sie die Anfrage und senden Sie die Antwort
"""
#Verarbeitung entsprechend dem Kunden...
Thread
ist eine Klasse, die im Modul threading
enthalten ist, einer integrierten Python-Bibliothek, und eine Basisklasse zum einfachen Erstellen von Threads.
Erstellen Sie bei Verwendung von "Thread" eine Klasse, die "Thread" erbt, und überschreiben Sie die Methode ".run ()". Eine Instanz dieser Klasse erstellt einen neuen Thread, indem sie die Methode ".start ()" aufruft und die Verarbeitung der Methode ".run ()" startet.
Die CPU kann keine Programme verarbeiten, die in einem Thread parallel ausgeführt werden, aber Programme, die in mehreren Threads ausgeführt werden, können parallel verarbeitet werden.
Bisher hat die Klasse "WebServer" alle Clientantworten nacheinander in einem einzelnen Thread verarbeitet.
Ab diesem Zeitpunkt wird die Antwort auf den Anforderungsinhalt jedoch parallel von einem anderen Thread verarbeitet, obwohl die Klasse "WebServer" mithilfe eines Threads eine Verbindung mit dem Client herstellen kann.
Dies vermeidet die Situation, in der eine Anforderung zu lang ist, um eine andere zu akzeptieren.
Grundsätzlich wird die Verarbeitung verschiedener Threads als separate Programme ausgeführt. Selbst wenn in einem Thread eine Ausnahme auftritt, wird diese nicht an einen anderen Thread weitergegeben.
In der Vergangenheit wurden Anforderungen beispielsweise im selben Thread verarbeitet. Wenn also während der Anforderungsverarbeitung eine Ausnahme aufgetreten ist, wäre die Hauptverarbeitung (Anforderungsempfangsverarbeitung) beendet worden, wenn die Ausnahme nicht behandelt worden wäre. Ab diesem Zeitpunkt werden Anforderungen in separaten Threads verarbeitet. Selbst wenn während der Verarbeitung einer Anforderung in einem bestimmten Thread eine Ausnahme auftritt und keine Ausnahmebehandlung erfolgt, wird dieser Thread nur beendet und der Hauptthread ist betroffen. da ist nicht.
Auf den ersten Blick mag es dankbar erscheinen, sollte aber im Falle einer Anomalie, die den gesamten Server betrifft, nicht fortgesetzt werden.
Achten Sie bei der Verwendung von Threads auf die Ausnahmebehandlung.
Das mehr und mehr verzweigte Threads bedeutet nicht, dass die Verarbeitung unendlich schnell sein wird.
Die Menge, die die CPU gleichzeitig verarbeiten kann, ist begrenzt. In einer Situation, in der die meisten parallel ausgeführten Prozesse eine große Menge an CPU verwenden, kann die Menge an Verarbeitung der CPU das Limit erreichen und die parallele Ausführung kann verzögert werden und die Leistung kann nicht verbessert oder verringert werden. Die Verarbeitung, die dazu führt, dass die CPU-Leistung zu einem Engpass wird und die Grenze der Verarbeitungsgeschwindigkeit erreicht, wird als "CPU-gebundene Verarbeitung" bezeichnet.
Wenn Sie bei Webdiensten mit viel CPU-gebundener Verarbeitung die Anzahl der Threads unnötig erhöhen, kann der Umfang der CPU-Verarbeitung an ihre Grenzen stoßen und die Ausführungsgeschwindigkeit anderer Programme beeinflussen. Dies soll verhindern, dass viele Webserver die Anzahl der Threads und Prozesse begrenzen.
Achten Sie darauf, wie viel Thread-Verzweigung Ihr Programm im schlimmsten Fall bewirkt.
Auch in diesem Buch sollten Sie ursprünglich eine Obergrenze für die Anzahl der Threads festlegen, die verzweigt werden können, und Python stellt zu diesem Zweck eine Klasse namens "ThreadPoolExecutor" bereit. Wenn Sie interessiert sind, überprüfen Sie es bitte.
Bewegen wir es tatsächlich.
Kapitel "Paralleles Verarbeiten von Anfragen"
Recommended Posts