Il existe des méthodes multi-processus, multi-thread et non bloquantes pour exécuter un autre processus avant qu'un processus ne soit terminé. Un processus est une unité de traitement qui possède sa propre mémoire, telle qu'une mémoire virtuelle, et la mémoire n'est pas partagée entre les processus. Puisqu'un thread est une unité de traitement dans un processus, les threads dans le même processus partagent la mémoire. Le non-blocage peut répondre à plusieurs demandes avec un seul thread.
Il existe deux méthodes de communication pour la communication par socket, "communication bloquante" et "communication non bloquante". Le blocage est une méthode de communication qui attend la fin de la transmission / réception, puis commence un autre traitement, il est donc souvent utilisé lors de l'exécution d'un traitement séquentiel. D'autre part, le non-blocage est une méthode de communication qui peut démarrer un autre traitement même si la communication n'est pas terminée, elle est donc souvent utilisée lors de l'exécution d'un traitement asynchrone.
Depuis Python 3.4, un module appelé ʻasyncio a été ajouté à la bibliothèque standard pour activer le traitement non bloquant ([Reference](http://qiita.com/icoxfog417/items/07cbf5110ca82629aca0)). À propos de ʻasyncio
, il est très facile à comprendre et est organisé en ici, et de nombreux exemples sont publiés.
Depuis ʻuWSGI1.9, le mode non bloquant est supporté comme décrit dans [ici](http://uwsgi-docs.readthedocs.io/en/latest/Async.html). De plus, depuis 2.0.4, ʻasyncio
est pris en charge (Reference).
Ci-dessous, exécutez dans l'environnement où Python 3.5 est installé.
greenlet
$ pip3 install greenlet
avec le support ʻasyncio
Tout d'abord, trouvez le répertoire où greenlet
est installé.$ find / -name greenlet -type d
Dans l'environnement de Mac OS
, le résultat était / Users / xxx / .pyenv / versions / 3.5.0 / include / python3.5m / greenlet
, alors exécutez ce qui suit.
$ CFLAGS="-I/Users/xxx/.pyenv/versions/3.5.0/include/python3.5m" UWSGI_PROFILE="asyncio" pip3 install uwsgi
Effectuez une vérification de fonctionnement simple avec blocage et non blocage. Dans l'exemple de code, le fichier est lu, mais ce qui suit est utilisé pour ce fichier.
numbers.txt
zero
one
two
three
four
five
De plus, lors de la vérification, ʻApache Bench` a été utilisé, mais lors de l'utilisation de local, [ici](https://stackoverflow.com/questions/7938869/ab-is-erroring-out-with-apr-socket- Il faut faire attention comme décrit dans recv-connection-refusée-61), et cette fois il est exécuté avec la commande suivante.
$ ab -n 10000 -c 100 http://127.0.0.1:9090/
avec
pip3 install uwsgi. Si vous avez déjà installé en mode non bloquant, désinstallez ʻuWSGI
une fois ci-dessous.$ pip3 unistall uwsgi
Enregistrez le contenu du fichier lu.
def application(environ, start_response):
def my_generator(name):
with open(name) as lines:
yield from lines
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("%s:%s" % (k, v), end="")
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
Exécutez avec le nombre de processus et de threads spécifié comme 1.
$ uwsgi --http-socket :9090 --processes 1 --threads 1 --logto uwsgi.log --wsgi-file webapp.py
Résultats ʻApache Bench` (partiels seulement).
Requests per second: 2694.06 [#/sec](mean)
Time per request: 37.119 [ms](mean)
Time per request: 0.371 [ms](mean, across all concurrent requests)
Transfer rate: 144.70 [Kbytes/sec] received
Sortie du journal du contenu du fichier lu de manière asynchrone après 5 secondes.
import asyncio
@asyncio.coroutine
def my_generator(name):
with open(name) as lines:
yield from lines
def read():
g = my_generator("numbers.txt")
for k, v in enumerate(g):
print("%s:%s" % (k, v), end="")
def application(environ, start_response):
asyncio.get_event_loop().call_later(5, read)
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
Exécutez en spécifiant 1 pour le nombre de processus et de threads comme dans le cas d'un blocage.
$ uwsgi --asyncio 2 --http-socket :9090 --greenlet --processes 1 --threads 1 --logto uwsgi.log --wsgi-file webapp.py
Ici, «2» est spécifié pour «--asyncio», mais lorsqu'il est défini sur «1», ce qui suit s'affiche et il ne démarre pas.
the greenlet suspend engine requires async mode
En regardant en «mode asynchrone», comme décrit ci-dessous, il y a une structure de mémoire appelée un noyau qui stocke les données pour chaque requête (définie comme un noyau car le concept de threads est déroutant).
Technically, cores are simple memory structures holding request’s data, but to give the user
the illusion of a multithreaded system we use that term.
Ces cœurs doivent être commutés, et ce n'est probablement que deux ou plus.
Each core can manage a single request, so the more core you spawn, more requests you will be
able to manage (and more memory you will use). The job of the suspend/resume engines is to stop
the current request management, move to another core, and eventually come back to the old one
(and so on).
Comparé au blocage, cet échantillon est légèrement plus lent en termes de performances. Il semble préférable de comparer avec d'autres échantillons.
equests per second: 2336.16 [#/sec](mean)
Time per request: 42.805 [ms](mean)
Time per request: 0.428 [ms](mean, across all concurrent requests)
Transfer rate: 125.48 [Kbytes/sec] received
Comme j'utilise 2 cœurs en mode non bloquant, j'ai réinstallé ʻuWSGI` et vérifié le nombre de threads avec 2. Le résultat est ci-dessous. Cela peut être un problème d'environnement Mac.
Requests per second: 2691.94 [#/sec](mean)
Time per request: 37.148 [ms](mean)
Time per request: 0.371 [ms](mean, across all concurrent requests)
Transfer rate: 144.59 [Kbytes/sec] received
Je voudrais étudier un peu plus ʻasyncio, introduire un cadre tel que
Flask`, et continuer la vérification qui sert également de recherche dans certaines conditions telles que l'utilisation de Nginx. Essayez également d'autres langages tels que la comparaison avec Golang.
Ici déclare «En cas de doute, n'utilisez pas le mode asynchrone», mais c'est toujours à un niveau pratique. N'est-il tout simplement pas atteint? Ou y a-t-il un moyen de le faire?
Recommended Posts