Saltar al contenido

Problema de productor / consumidor con multiprocesamiento de Python

Solución:

Creo que debe haber algo mal con la parte del servidor web, ya que funciona perfectamente:

from multiprocessing import Process, Queue, cpu_count
import random
import time


def serve(queue):
    works = ["task_1", "task_2"]
    while True:
        time.sleep(0.01)
        queue.put(random.choice(works))


def work(id, queue):
    while True:
        task = queue.get()
        if task is None:
            break
        time.sleep(0.05)
        print "%d task:" % id, task
    queue.put(None)


class Manager:
    def __init__(self):
        self.queue = Queue()
        self.NUMBER_OF_PROCESSES = cpu_count()

    def start(self):
        print "starting %d workers" % self.NUMBER_OF_PROCESSES
        self.workers = [Process(target=work, args=(i, self.queue,))
                        for i in xrange(self.NUMBER_OF_PROCESSES)]
        for w in self.workers:
            w.start()

        serve(self.queue)

    def stop(self):
        self.queue.put(None)
        for i in range(self.NUMBER_OF_PROCESSES):
            self.workers[i].join()
        self.queue.close()


Manager().start()

Salida de muestra:

starting 2 workers
0 task: task_1
1 task: task_2
0 task: task_2
1 task: task_1
0 task: task_1

“Segunda pregunta, ¿cuál es la mejor manera de detener correctamente el servidor HTTP?”

Esto es duro.

Tiene dos opciones para la comunicación entre procesos:

  • Controles fuera de banda. El servidor tiene otro mecanismo de comunicación. Otro zócalo, una señal Unix o algo más. La otra cosa podría ser un archivo “detener ahora” en el directorio local del servidor. Parece extraño, pero funciona bien y es más sencillo que introducir un bucle de selección para escuchar en varios sockets o un controlador de señal para captar una señal Unis.

    El archivo “detener ahora” es fácil de implementar. los evwsgi.run() loop simplemente busca este archivo después de cada solicitud. Para hacer que el servidor se detenga, cree el archivo, ejecute un /control request (que obtendrá un error 500 o algo así, realmente no importa) y el servidor debería detenerse. Recuerde eliminar el archivo stop-now, de lo contrario su servidor no se reiniciará.

  • Controles en banda. El servidor tiene otra URL (/stop) que lo detendrá. Superficialmente, esto parece una pesadilla de seguridad, pero depende completamente de dónde y cómo se usará este servidor. Dado que parece ser un simple contenedor alrededor de una cola de solicitudes internas, esta URL adicional funciona bien.

    Para que esto funcione, debe escribir su propia versión de evwsgi.run() que se puede terminar estableciendo alguna variable de una manera que salga del bucle.

Editar

Probablemente no desee terminar su servidor, ya que no conoce el estado de sus subprocesos de trabajo. Necesita señalar al servidor y luego solo tiene que esperar hasta que termine las cosas normalmente.

Si desea matar a la fuerza al servidor, entonces os.kill() (o multiprocessing.terminate) trabajará. Excepto, por supuesto, que no sabes qué estaban haciendo los hilos secundarios.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *