2012-03-14 133 views
0

我们使用芹菜从不同的旅行中获取航班数据 机构,每个请求需要约20-30秒(大多数机构需要 请求序列 - 授权,发送请求,投票结果) 。芹菜+ eventlet = 100%CPU使用率

普通 芹菜任务看起来是这样的:

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池并发性300运行, prefetch_multiplier = 1broker_limit = 300 当〜100-200的任务是从队列中取出 - CPU使用率上扬到100% (使用整个CPU核心)并且从队列中取出任务 有延迟。

请您指出可能的问题 - 阻止 操作(eventlet ALARM DETECTOR不会例外),错误的 体系结构或其他。

+0

我一直调查有关高CPU使用率的报告,只有在升级到2.5.x后才会发生。我还没有能够重现,因为我还没有收到任何例子。但也许这会做这项工作,我会尽力回报。谢谢! – asksol 2012-04-04 11:33:24

回答

0

如果您向服务器发出200个请求,则响应可能会延迟,因此urllib.urlopen将挂起,则会出现问题。

另一件我注意到的事情:如果发生URLError,程序会停留在while循环中,直到睡眠时间大于10为止。所以URLError错误会让这个脚本睡眠55秒(1 + 2 + 3 .. etc )

+0

urllib.urlopen - 应该是一个问题 - 为什么我使用eventlet的主要目的是为了避免挂起。你提到的第二个问题并不是真实的,这只是由于代码简化之前发布 – Andrew 2012-03-14 17:18:19

+0

对不起,没有注意到! – Willian 2012-03-14 17:24:45

0

对不起,延迟回复。

事情我会尝试在这种情况下首先在Celery和您的代码中完全关闭Eventlet,使用进程或操作系统线程模型。 300线程或者甚至进程对于OS调度器来说没有那么多的负载(尽管你可能缺少运行很多进程的内存)。所以我会尝试一下,看看CPU负载是否急剧下降。如果没有,那么问题出现在你的代码中,Eventlet无法神奇地修复它。但是,如果它确实下降了,我们需要更密切地调查这个问题。

如果错误仍然存​​在,请通过以下任一方式举报: