Обработка одновременных / асинхронных запросов с помощью 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 секунд для завершения.