2014-12-14 3 views
1

В моем текущем приложении я использую Tornado AsyncHttpClient для запросов на веб-сайт. Поток сложный, обрабатывая ответы от предыдущих запросов в другом запросе.Почему AsyncHTTPClient в Tornado не отправляет запрос немедленно?

На самом деле, я загружаю статью, а затем проанализировать его и загрузить изображения уже в нем

Что меня беспокоит то, что в то время как в моем журнале я ясно вижу сообщение о том, что .fetch() на фото URL не beeen выдан, никакой фактической запрос HTTP производится, как понюхал в Wireshark

Я пытался возиться с max_client_count и Curl/простым клиентом HTTP, но bahvior всегда то же самое - пока все статьи не будут загружены не запросы фото на самом деле выдается. Как это изменить?

upd. некоторый псевдокод

@VictorSergienko Я нахожусь в Linux, поэтому по умолчанию, я думаю, используется версия EPoll. Вся система слишком сложна, но она сводится к:

@gen.coroutine 
def fetch_and_process(self, url, callback): 
    body = yield self.async_client.fetch(url) 
    res = yield callback(body) 
    return res 

@gen.coroutine 
def process_articles(self,urls): 
    wait_ids=[] 
    for url in urls: 
    #Enqueue but don't wait for one 
    IOLoop.current().add_callback(self.fetch_and_process(url, self.process_article)) 
    wait_ids.append(yield gen.Callback(key=url)) 
    #wait for all tasks to finish 
    yield wait_ids 

@gen.coroutine 
def process_article(self,body): 
    photo_url=self.extract_photo_url_from_page(body) 
    do_some_stuff() 
    print('I gonna download that photo '+photo_url) 
    yield self.download_photo(photo_url) 

@gen.coroutine 
def download_photo(self, photo_url): 
    body = yield self.async_client.fetch(photo_url) 
    with open(self.construct_filename(photo_url)) as f: 
    f.write(body) 

И когда он печатает Я собираюсь скачать эту фотографию никакого фактического запроса не выполнен! Вместо этого он продолжает загружать больше статей и enqueueing больше фотографий untils все статьи загружаются, только тогда все фотографии запрашиваются в объеме

+0

Я еще не знаю ответа, но, возможно, если вы разделите небольшой образец кода, который воспроизводит проблему, я могу помочь отладить его. –

+0

Главный вопрос: на чем работает ioloop. Кодовый фрагмент определенно поможет. –

+0

@VictorSergienko, добавленный пример – Ojomio

ответ

1

AsyncHTTPClient имеет очередь, которую вы заполняете сразу же в process_articles ("Ставить но дон «Подождите один»). К моменту обработки первой статьи его фотографии будут отправляться в конце очереди после всех других статей.

Если вы использовали yield self.fetch_and_process вместо add_callback в process_articles, вы можете чередовать статьи и их фотографии, но вы могли загружать только одну вещь за раз. Чтобы поддерживать баланс между статьями и фотографиями при одновременном загрузке нескольких предметов, рассмотрите возможность использования пакета toro для примитивов синхронизации. Пример в http://toro.readthedocs.org/en/stable/examples/web_spider_example.html похож на ваш прецедент.

+0

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

+0

Очередь не ограничена; вы можете сразу изменить количество запросов в полете с аргументом ключевого слова 'max_clients' в AsyncHTTPClient (либо конструктор, либо метод класса configure, прочитайте документы о магии в конструкторе AsyncHTTPClient). Тайм-ауты запроса включают время, потраченное в очереди. –

+0

Спасибо за 'торо', что определенно полезно. Однако я не чувствую, что могу контролировать таймауты с помощью 'request_timeout' или' connection_timeout': я, например, задаю 60 секунд как задержку, но в какой-то момент я получаю сообщение, подобное _Request, после истечения 30000 ...._. Более того, иногда они рассказывают мне о «разрешении таймаута», который я понимаю, что означает, но не знаю, как настроить – Ojomio

Смежные вопросы