Подтвердить что ты не робот

Многопоточный веб-сервер в python

Я пытаюсь создать многопоточный веб-сервер в python, но он реагирует только на один запрос за раз, и я не могу понять, почему. Можете ли вы мне помочь, пожалуйста?

#!/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()
4b9b3361

Ответ 1

Отметьте эту статью из блога Дуга Хеллмана.

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 <Ctrl-C> to stop'
    server.serve_forever()

Ответ 3

Я разработал Утилиту PIP под названием ComplexHTTPServer, которая является многопоточной версией SimpleHTTPServer.

Чтобы установить его, все, что вам нужно сделать, это:

pip install ComplexHTTPServer

Использование его так же просто, как:

python -m ComplexHTTPServer [PORT]

(По умолчанию порт 8000.)

Ответ 4

Удивительно, сколько голосов получают эти решения, которые нарушают потоковое вещание. Если потоковая передача может понадобиться по дороге, то ThreadingMixIn и gunicorn не подходят, потому что они просто собирают ответ и записывают его как единицу в конце (что фактически ничего не делает, если ваш поток бесконечен).

Ваш основной подход объединения BaseHTTPServer с потоками в порядке. Но настройки по умолчанию BaseHTTPServer повторно связывают новый сокет на каждом слушателе, который не будет работать в Linux, если все слушатели находятся на одном и том же порту. Измените эти настройки перед вызовом serve_forever(). (Так же, как вы должны установить self.daemon = True в потоке, чтобы остановить ctrl-C от отключения.)

Следующий пример запускает 100 потоков обработчиков на одном и том же порту, причем каждый обработчик запускается через 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/info/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)