Le chapitre "Traitement des requêtes en parallèle" a été mis à jour.
Si vous voulez en savoir plus, veuillez "aimer" ou "me suivre" dans Book ;-)
Ce qui suit est un extrait du contenu du livre.
python lit le code source dans l'ordre à partir du haut, et lorsque le traitement d'une ligne est terminé, il exécute la ligne suivante dans l'ordre.
Par conséquent, avec le code source actuel,
--Accepter les connexions des clients (. Accept ()
)
.handle_client ()
)
-Fin de la communication avec le client (après avoir géré les exceptions si nécessaire) (.close ()
)
--Accepter les connexions des clients (. Accept ()
)Assurez-vous de suivre cet ordre.
En d'autres termes, ** "La prochaine demande ne sera pas acceptée tant que tout le traitement d'une demande ne sera pas terminé" ** Cela signifie que.
Cela devient un gros problème à mesure que le nombre de demandes augmente.
Par exemple, supposons que 10 demandes arrivent en même temps.
À ce moment, le serveur commencera à traiter la première demande qui vient en premier. Et si cette première demande est un processus très long, les 9 demandes suivantes devront attendre que le processus soit terminé.
Un cas courant consiste à lancer une requête avec des critères de recherche complexes sur un serveur de base de données et à attendre 30 secondes pour une réponse. Les performances globales seront bien meilleures si la machine traite les 9 autres requêtes pendant 30 secondes en attendant une réponse de la base de données.
De cette manière, pendant qu'un certain programme exécute un certain processus, l'exécution d'un autre programme en arrière-plan est appelée ** traitement parallèle ** ou ** traitement parallèle **.
Ce traitement parallèle est implémenté naturellement pour les serveurs Web généraux, donc implémentons-le également.
Permettez-moi d'expliquer la différence entre «traitement parallèle» et «traitement parallèle».
En général, traiter plusieurs monogoto en même temps est appelé "traitement parallèle".
Dans le monde informatique, le processeur est responsable de tout le traitement réel, mais un processeur ne peut toujours faire qu'un seul travail à la fois. Par conséquent, au sens strict, le "traitement parallèle" ne peut pas être réalisé avec une seule CPU.
Cependant, d'un point de vue humain, le traitement du processeur est si rapide que «Si vous faites ce travail et devenez" en attente ", passez à un autre travail, et si vous devenez" en attente "à nouveau, faites un autre travail." ` En changeant les processus à aborder l'un après l'autre, l'œil humain peut le voir comme s'il effectuait des tâches en même temps. (Selon le système d'exploitation, le processeur change de tâches l'une après l'autre en 0,2 seconde ou moins)
Dans l'ancien temps, il était naturel pour un ordinateur d'avoir un processeur, donc dans le monde informatique, il n'y avait pas de problème particulier à lire ce "traitement pseudo-parallèle" simplement comme "traitement parallèle". Cependant, vers 2000, avec la sortie / diffusion des processeurs dual-core, un ordinateur est venu à être équipé de deux ou quatre processeurs (plus précisément, des cœurs de processeur), et en faisant fonctionner ces processeurs en même temps, "pseudo" Il est devenu possible d'effectuer un "traitement parallèle réel" au lieu d'un "traitement parallèle".
Par conséquent, les programmeurs appellent «traitement pseudo-parallèle» «traitement ** parallèle **» afin de faire la distinction entre «traitement pseudo-parallèle» et «traitement vrai parallèle», qui étaient auparavant lus comme «traitement parallèle». Il est venu pour être.
Il est extrêmement difficile pour les humains de faire la distinction entre «traitement parallèle» et «traitement parallèle» en surface, et il n'est pratiquement pas nécessaire de faire la distinction entre les deux en termes de programmation tant que le réglage des performances de la machine n'est pas nécessaire. Par conséquent, dans ce document, ceux-ci sont collectivement appelés "traitement parallèle" sans aucune distinction particulière.
C'est une histoire très compliquée de savoir quand le traitement parallèle et le traitement parallèle sont utilisés correctement et comment ils affectent les performances. Je vais l'omettre dans ce livre. Il y a beaucoup d'informations disponibles sur Internet à ce sujet, donc si vous êtes intéressé, jetez-y un œil.
Voici le code source amélioré pour le traitement parallèle. Veuillez noter qu'il existe deux fichiers.
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
Les fichiers étant séparés, les caractères «Serveur:» et «Travailleur:» sont respectivement sortis dans le journal affichant l'enregistrement de traitement. Exemple)
print("=== Server:Démarrez le serveur===")
print("=== Worker:Mettre fin à la communication avec le client===")
WebServer.py
#Créer un thread pour gérer le client
thread = WorkerThread(client_socket)
#Exécuter le fil
thread.start()
Créez un ** thread ** pour traiter le client qui a établi la connexion et démarrer le traitement du thread.
Le traitement qui a été effectué par la méthode .handle_client ()
jusqu'à la dernière fois et le traitement des exceptions avant et après ont tous été déplacés vers le traitement dans ce thread.
Un ** thread ** est une séquence de traitement qui permet à un ordinateur de traiter en parallèle, ce qui sera expliqué en détail plus loin.
WorkerThread.py
class WorkerThread(Thread):
#Répertoire avec fichiers exécutables
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#Répertoire pour placer les fichiers à livrer de manière statique
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:
"""
Reçoit une socket connectée au client comme argument
Traitez la demande et envoyez la réponse
"""
#Traitement correspondant au client...
Thread
est une classe incluse dans le module threading
, qui est une bibliothèque intégrée de python, et est une classe de base pour créer facilement des threads.
Lorsque vous utilisez Thread
, créez une classe qui hérite de Thread
et remplacez la méthode.run ()
.
Une instance de cette classe crée un nouveau thread en appelant la méthode .start ()
et démarre le traitement de la méthode .run ()
.
La CPU ne peut pas traiter les programmes exécutés dans un thread en parallèle, mais les programmes exécutés dans plusieurs threads peuvent être traités en parallèle.
Auparavant, la classe WebServer
traitait toutes les réponses client de manière séquentielle dans un seul thread.
Cependant, à partir de ce moment, bien que la classe WebServer
puisse établir une connexion avec le client en utilisant un thread, la réponse au contenu de la requête est traitée en parallèle par un autre thread.
Cela évite la situation où une demande est trop longue pour en accepter une autre.
Fondamentalement, le traitement de différents threads s'exécute en tant que programmes séparés, donc même si une exception se produit dans un thread, elle ne sera pas propagée à un autre thread.
Par exemple, dans le passé, les demandes étaient traitées dans le même thread, donc si une exception se produisait pendant le traitement de la demande, le traitement principal (traitement de la réception de la demande) aurait pris fin à moins que l'exception ne soit traitée. À partir de ce moment, les demandes sont traitées dans des threads séparés, donc même si une exception se produit lors du traitement d'une demande dans un certain thread, s'il n'y a pas de gestion des exceptions, ce thread se terminera simplement et le thread principal sera affecté. il n'y a pas.
À première vue, cela peut paraître reconnaissant, mais cela ne devrait pas continuer en cas d'anomalie affectant l'ensemble du serveur.
Soyez sensible à la gestion des exceptions lors de l'utilisation de threads.
De plus, le fait de ramener de plus en plus les threads ne signifie pas que le traitement sera infiniment rapide.
Il y a une limite à la quantité que la CPU peut traiter en même temps. Dans une situation où la plupart des processus exécutés en parallèle utilisent une grande quantité de CPU, la quantité de traitement de la CPU peut atteindre la limite et l'exécution parallèle peut être retardée, et les performances peuvent ne pas être améliorées ou peuvent être diminuées. Le traitement qui fait que les performances du processeur deviennent un goulot d'étranglement et atteint la limite de vitesse de traitement est appelé «traitement lié au processeur».
Pour les services Web qui ont beaucoup de traitement lié au processeur, si vous augmentez inutilement le nombre de threads, la quantité de traitement du processeur peut atteindre sa limite et affecter la vitesse d'exécution d'autres programmes. De nombreux serveurs Web vous permettent de limiter le nombre de threads et de processus pour éviter cela.
Faites attention au nombre de branches de thread que votre programme aura dans le pire des cas.
Dans ce livre également, vous devez à l'origine définir une limite supérieure sur le nombre de threads qui peuvent être branchés, et python fournit une classe appelée ThreadPoolExecutor
à cet effet.
Si vous êtes intéressé, veuillez le vérifier.
Déplaçons-le réellement.
Chapitre "Traitement des requêtes en parallèle"
Recommended Posts