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

Медленный HTTP-сервер Python на localhost

У меня возникают некоторые проблемы с производительностью при создании очень простого HTTP-сервера Python. Основная проблема заключается в том, что производительность зависит от того, какой клиент я использую для доступа к ней, где сервер и все клиенты запускаются на локальном компьютере. Например, запрос GET, выданный с Python script (urllib2.urlopen('http://localhost/').read()) принимает только за секунду до завершения, что кажется медленным, учитывая, что сервер не загружается. Выполнение запроса GET из Excel с использованием MSXML2.ServerXMLHTTP также мешает. Однако, запрашивая данные Google Chrome или RCURL, надстройка curl для R дает практически мгновенный отклик, чего я ожидаю.

Добавление к моей путанице заключается в том, что я не испытываю проблем с производительностью для любого клиента, когда я нахожусь на своем компьютере на работе (проблемы с производительностью на моем домашнем компьютере). Обе системы используют Python 2.6, хотя рабочий компьютер работает под управлением Windows XP вместо 7.

Ниже приведен мой очень простой пример сервера, который просто возвращает "Hello world" для любого запроса на получение.

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print("Just received a GET request")
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

        self.wfile.write('Hello world')

        return

    def log_request(self, code=None, size=None):
        print('Request')

    def log_message(self, format, *args):
        print('Message')

if __name__ == "__main__":
    try:
        server = HTTPServer(('localhost', 80), MyHandler)
        print('Started http server')
        server.serve_forever()
    except KeyboardInterrupt:
        print('^C received, shutting down server')
        server.socket.close()

Обратите внимание, что в MyHandler я переопределяю функции log_request() и log_message(). Причина в том, что я прочитал, что полноценный поиск имени домена, выполняемый одной из этих функций, может быть причиной медленного сервера. К сожалению, установка их только для печати статического сообщения не решила мою проблему.

Также обратите внимание, что я поставил инструкцию print() в качестве первой строки в do_GET() в MyHandler. Медленность происходит до того, как это сообщение будет напечатано, что означает, что ни одна из вещей, которые появляются после него, вызывает задержку.

4b9b3361

Ответ 1

Это не похоже на проблему с кодом. Отличным способом устранения неполадок с HTTP-сервером является подключение к нему telnet к нему на порт 80. Затем вы можете ввести что-то вроде:

GET /index.html HTTP/1.1
host: www.blah.com
<enter> <enter>

и наблюдать за ответом сервера. Посмотрите, получаете ли вы задержку, используя этот подход.

Вы также можете отключить любые брандмауэры, чтобы убедиться, что они несут ответственность за замедление.

Попробуйте заменить 127.0.0.1 на localhost. Если это решает проблему, то это ключ к тому, что поиск FQDN действительно может быть возможной причиной.

Ответ 2

Обработчик запроса выдает обратный поиск имени, чтобы отобразить имя клиента в журнале. Моя Windows 7 выдает первый DNS-запрос, который завершается неудачно без задержки, после чего 2 последовательных запроса имени NetBIOS отправляются HTTP-клиенту, и каждый из них запускается с 2-секундным таймаутом = 4-секундная задержка !!

Посмотрите на https://bugs.python.org/issue6085

Другое исправление, которое сработало для меня, это переопределение BaseHTTPRequestHandler.address_string() в моем обработчике запросов с версией, которая не выполняет поиск имени

def address_string(self):
    host, port = self.client_address[:2]
    #return socket.getfqdn(host)
    return host

Philippe