Обработка одновременных / асинхронных запросов с помощью Python BaseHTTPServer

Я настроил HTTP-сервер с потоком (с потоками Python), создав класс, который наследуется от HTTPServer и ThreadingMixIn:

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

у меня есть класс обработчика, который наследуется от BaseHTTPRequestHandler, и я запускаю сервер с чем-то вроде этого:

class MyHandler(BaseHTTPRequestHandler):
    ...

server = ThreadedHTTPServer(('localhost', 8080), MyHandler)
# Prevent issues with socket reuse
server.allow_reuse_address = True
# Start the server
server.serve_forever()

Это все довольно просто. Проблема, с которой я сталкиваюсь, заключается в том, что ThreadingMixIn, ForkingMixIn или иначе запрос блокируется обработчиком запроса для возврата. Это можно легко увидеть, реализовав этот пример кода:

class MyHandler(BaseHTTPRequestHandler):
    def respond(self, status_code):
        self.send_response(status_code)
        self.end_headers()

    def do_GET(self):
         print "Entered GET request handler"
         time.sleep(10)
         print "Sending response!"
         respond(200)

Если бы сервер обрабатывал их одновременно, то мы могли бы отправить два запроса и увидеть, как сервер вводит оба обработчика запросов GET перед отправкой любого ответа. Вместо этого сервер вводит обработчик запроса GET для первого запроса, ждет его возврата, а затем вводит его для второго (поэтому второй запрос занимает ~20 секунд, чтобы вернуться вместо 10).

есть простой способ для меня реализовать систему, где сервер не ждет возвращения обработчика? В частности, я пытаюсь написать систему, которая ждет получения нескольких запросов, прежде чем возвращать любой из них (форма длительного опроса) и сталкивается с проблемами, когда ожидание первого запроса блокирует любые будущие запросы от подключения к серверу.

1 ответов


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

достаточно. Ваш клиент, вероятно, не делает параллельных запросов. Если запросы выполняются параллельно, потоковый сервер работает так, как ожидалось. Вот клиент:

#!/usr/bin/env python
import sys
import urllib2

from threading import Thread

def make_request(url):
    print urllib2.urlopen(url).read()

def main():
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 8000
    for _ in range(10):
        Thread(target=make_request, args=("http://localhost:%d" % port,)).start()

main()

и соответствующий сервер:

import time
from BaseHTTPServer   import BaseHTTPRequestHandler, HTTPServer, test as _test
from SocketServer     import ThreadingMixIn


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

class SlowHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()

        self.wfile.write("Entered GET request handler")
        time.sleep(1)
        self.wfile.write("Sending response!")

def test(HandlerClass = SlowHandler,
         ServerClass = ThreadedHTTPServer):
    _test(HandlerClass, ServerClass)


if __name__ == '__main__':
    test()

все 10 запросов заканчиваются через 1 секунду. Если убрать ThreadingMixIn из определения сервера тогда все 10 запросов занимают 10 секунд для завершения.