unos días me ha hecho una pregunta sobre SO trata de ayudar a diseñar un paradigma para la estructuración de múltiples peticiones HTTPdiferencias se obtiene al usar corrutinas vs roscado hace
Este es el escenario. Me gustaría tener un sistema multi-productor, multi-consumidor. Mis productores rastrean y rastrean algunos sitios y agregan los enlaces que encuentra en una cola. Como voy a rastrear varios sitios, me gustaría tener varios productores/rastreadores.
Los consumidores/trabajadores se alimentan de esta cola, realizan solicitudes TCP/UDP a estos enlaces y guardan los resultados en mi Django DB. También me gustaría tener trabajadores múltiples ya que cada elemento de la cola es totalmente independiente el uno del otro.
Las personas sugirieron que se use una biblioteca de coroutine para esto, es decir, Gevent o Eventlet. Como nunca trabajé con corutinas, leí que aunque el paradigma de programación es similar a los paradigmas de subprocesos, solo un subproceso se está ejecutando activamente, pero cuando se producen llamadas, como las llamadas de E/S, las pilas se cambian en memoria y el otro verde el hilo toma el control hasta que encuentra algún tipo de llamada de E/S de bloqueo. Espero tener esto bien? Aquí está el código de uno de mis mensajes SO:
import gevent
from gevent.queue import *
import time
import random
q = JoinableQueue()
workers = []
producers = []
def do_work(wid, value):
gevent.sleep(random.randint(0,2))
print 'Task', value, 'done', wid
def worker(wid):
while True:
item = q.get()
try:
print "Got item %s" % item
do_work(wid, item)
finally:
print "No more items"
q.task_done()
def producer():
while True:
item = random.randint(1, 11)
if item == 10:
print "Signal Received"
return
else:
print "Added item %s" % item
q.put(item)
for i in range(4):
workers.append(gevent.spawn(worker, random.randint(1, 100000)))
# This doesn't work.
for j in range(2):
producers.append(gevent.spawn(producer))
# Uncommenting this makes this script work.
# producer()
q.join()
Esto funciona bien porque los sleep
llamadas son llamadas de bloqueo y cuando se produce un evento sleep
, otro hilo verde se hace cargo. Esto es mucho más rápido que la ejecución secuencial. Como puede ver, no tengo ningún código en mi programa que deliberadamente ceda la ejecución de un hilo a otro. No veo cómo encaja esto en el escenario anterior, ya que me gustaría tener todos los subprocesos ejecutándose simultáneamente.
Todo funciona bien, pero creo que el rendimiento que he logrado con Gevent/Eventlets es mayor que con el programa secuencial original, pero drásticamente más bajo que con el real-threading.
Si tuviera que volver a implementar mi programa mediante el uso de mecanismos de enhebrado, cada uno de mis productores y consumidores podría estar trabajando simultáneamente sin la necesidad de intercambiar las pilas como corutinas.
¿Debería volver a implementarse utilizando el enhebrado? ¿Está mal mi diseño? No he podido ver los beneficios reales del uso de corutinas.
Tal vez mis conceptos son un poco embarrados, pero esto es lo que he asimilado. Cualquier ayuda o aclaración de mi paradigma y conceptos sería genial.
Gracias
¿Por qué no utilizar procesos múltiples? –
No conozco los pros y contras de multi-threading versus multi-processing, así que no sé si está bien o no. –
no existe el "enhebrado real" (solo se ejecuta un subproceso del sistema operativo real en un momento dado) en programas Python sin recurrir a extensiones C (o procesos de SO pesados) debido al bloqueo de Intérprete global. –