Servidor web multiproceso en python.

Estoy tratando de crear un servidor web multiproceso en Python, pero solo responde a una solicitud a la vez y no puedo entender por qué. ¿Puedes ayudarme por favor?

#!/usr/bin/env python2 # -*- coding: utf-8 -*- from SocketServer import ThreadingMixIn from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler from time import sleep class ThreadingServer(ThreadingMixIn, HTTPServer): pass class RequestHandler(SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type', 'text/plain') sleep(5) response = 'Slept for 5 seconds..' self.send_header('Content-length', len(response)) self.end_headers() self.wfile.write(response) ThreadingServer(('', 8000), RequestHandler).serve_forever() 

Revisa esta publicación del blog de Doug Hellmann.

 from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from SocketServer import ThreadingMixIn import threading class Handler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.end_headers() message = threading.currentThread().getName() self.wfile.write(message) self.wfile.write('\n') return class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread.""" if __name__ == '__main__': server = ThreadedHTTPServer(('localhost', 8080), Handler) print 'Starting server, use  to stop' server.serve_forever() 

He desarrollado una utilidad PIP llamada ComplexHTTPServer que es una versión de subprocesos múltiples de SimpleHTTPServer.

Para instalarlo, todo lo que necesitas hacer es:

 pip install ComplexHTTPServer 

Su uso es tan simple como:

 python -m ComplexHTTPServer [PORT] 

(De forma predeterminada, el puerto es 8000.)

Aquí hay otro buen ejemplo de un servidor HTTP de tipo SimpleHTTPServer multiproceso: MultithreadedSimpleHTTPServer en GitHub .

Es sorprendente cuántos votos obtienen estas soluciones que rompen la transmisión. Si la transmisión puede ser necesaria en el futuro, ThreadingMixIn y gunicorn no son buenos porque simplemente recostackn la respuesta y la escriben como una unidad al final (lo que en realidad no hace nada si tu transmisión es infinita).

Su enfoque básico de combinar BaseHTTPServer con subprocesos está bien. Pero la configuración predeterminada de BaseHTTPServer vuelve a enlazar un nuevo socket en cada escucha, que no funcionará en Linux si todos los escuchas están en el mismo puerto. Cambie esos ajustes antes de la llamada serve_forever() . (Al igual que tiene que establecer self.daemon = True en un hilo para evitar que ctrl-C se deshabilite).

El siguiente ejemplo lanza 100 hilos de controlador en el mismo puerto, con cada controlador iniciado a través de BaseHTTPServer .

 import time, threading, socket, SocketServer, BaseHTTPServer class Handler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): if self.path != '/': self.send_error(404, "Object not found") return self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() # serve up an infinite stream i = 0 while True: self.wfile.write("%i " % i) time.sleep(0.1) i += 1 # Create ONE socket. addr = ('', 8000) sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(addr) sock.listen(5) # Launch 100 listener threads. class Thread(threading.Thread): def __init__(self, i): threading.Thread.__init__(self) self.i = i self.daemon = True self.start() def run(self): httpd = BaseHTTPServer.HTTPServer(addr, Handler, False) # Prevent the HTTP server from re-binding every handler. # https://stackoverflow.com/questions/46210672/ httpd.socket = sock httpd.server_bind = self.server_close = lambda self: None httpd.serve_forever() [Thread(i) for i in range(100)] time.sleep(9e9) 

En python3, puedes usar el siguiente código (https o http):

 from http.server import HTTPServer, BaseHTTPRequestHandler from socketserver import ThreadingMixIn import threading USE_HTTPS = True class Handler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.end_headers() self.wfile.write(b'Hello world\t' + threading.currentThread().getName().encode() + b'\t' + str(threading.active_count()).encode() + b'\n') class ThreadingSimpleServer(ThreadingMixIn, HTTPServer): pass def run(): server = ThreadingSimpleServer(('0.0.0.0', 4444), Handler) if USE_HTTPS: import ssl server.socket = ssl.wrap_socket(server.socket, keyfile='./key.pem', certfile='./cert.pem', server_side=True) server.serve_forever() if __name__ == '__main__': run() 

Descubrirá que este código creará un nuevo hilo para tratar con cada solicitud.

Comando a continuación para generar el certificado de autofirmación:

 openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 

Si estás usando Flask, este blog es genial.