2012-03-14 4 views
0

Мы используем сельдерей для получения данных о рейсах из разных поездок агентств, каждый запрос занимает ~ 20-30 секунд (большинство агентств требуют последовательность запросов - авторизация, отправка запроса, опрос результатов) ,celery + eventlet = 100% Использование ЦП

Нормальная сельдерей задача выглядит следующим образом:

from eventlet.green import urllib2, time 
def get_results(attr, **kwargs): 
    search, provider, minprice = attr 
    data = XXX # prepared data 
    host = urljoin(MAIN_URL, "RPCService/Flights_SearchStart") 
    req = urllib2.Request(host, data, {'Content-Type': 'text/xml'}) 
    try: 
     response_stream = urllib2.urlopen(req) 
    except urllib2.URLError as e: 
     return [search, None] 
    response = response_stream.read() 
    rsp_host = urljoin(MAIN_URL, "RPCService/FlightSearchResults_Get") 
    rsp_req = urllib2.Request(rsp_host, response, {'Content-Type': 
'text/xml'}) 
    ready = False 
    sleeptime = 1 
    rsp_response = '' 
    while not ready: 
     time.sleep(sleeptime) 
     try: 
      rsp_response_stream = urllib2.urlopen(rsp_req) 
     except urllib2.URLError as e: 
      log.error('go2see: results fetch failed for %s IOError %s'% 
(search.id, str(e))) 
     else: 
      rsp_response = rsp_response_stream.read() 
      try: 
       rsp = parseString(rsp_response) 
      except ExpatError as e: 
       return [search, None] 
      else: 
       ready = rsp.getElementsByTagName('SearchResultEx') 
[0].getElementsByTagName('IsReady')[0].firstChild.data 
       ready = (ready == 'true') 
     sleeptime += 1 
     if sleeptime > 10: 
      return [search, None] 
    hash = "%032x" % random.getrandbits(128) 
    open(RESULT_TMP_FOLDER+hash, 'w+').write(rsp_response) 
    # call to parser 
    parse_agent_results.apply_async(queue='parsers', args=[__name__, 
search, provider, hash]) 

Эти задачи выполняются в eventlet бассейне с concurency 300, prefetch_multiplier = 1, broker_limit = 300 При ~ 100-200 задачи выбираются из очереди - использование CPU поднимает вверх до 100% (используется весь ядро ​​центрального процессора) и выполняется выборка задачи из очереди с задержками.

Не могли бы вы указать возможные проблемы - блокировка операции (eventlet ALARM DETECTOR не дает никаких исключений), неправильная архитектура или что-то еще.

+0

Я был расследование сообщений о высоком использовании ЦП, которое происходит только после обновления до 2.5.x. Я еще не смог воспроизвести, так как я не получил никакого примера. Но, возможно, это сработает, я постараюсь и отчитаюсь. Благодаря! – asksol

ответ

0

Проблема возникает, если вы запускаете 200 запросов на сервер, ответы могут быть отложены, и поэтому urllib.urlopen будет висеть.

Еще одна вещь, которую я заметил: если URLError поднят, программа остается в цикле while до тех пор, пока не будет равна 10. Таким образом, ошибка URLError позволит этому сценарию спящий на 55 секунд (1 + 2 + 3 .. и т. Д.).)

+0

urllib.urlopen - должна быть проблема - основная цель, почему я использовал eventlet - избегать зависаний. второй вопрос, который вы упомянули, не является реальным, это просто из-за упрощения кода перед публикацией – Andrew

+0

Извините, не заметил этого! – Willian

0

Извините за поздний отклик.

Вещь, которую я постараюсь сначала в такой ситуации, - полностью отключить Eventlet как в сельдерее, так и в вашем коде, использовать модель процесса или ОС. 300 потоков или даже процессов не так много нагрузки для планировщика ОС (хотя вам может не хватать памяти для запуска многих процессов). Поэтому я бы попробовал и посмотрел, падает ли загрузка процессора резко. Если это не так, тогда проблема в вашем коде, и Eventlet не может магически исправить это. Однако, если это произойдет, нам нужно будет исследовать проблему ближе.

Если ошибка не устранена, пожалуйста, сообщите об этом с помощью любого из следующих способов:

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