2013-03-11 116 views
0

我正在使用python線程來解析網站IP地址。這是我解決問題的工作流程。這是一個守護線程。Python線程似乎凍結了機器

def get_ip_worker(): 
    """This is the worker (thread) process for parsing ips, this process takes domain from the q processes it 
    and then saves it to another q""" 

    socket.setdefaulttimeout(3) 
    while True: 
     domain = domains_q.get() 
     try: 
      addr_info = socket.getaddrinfo(domain, 80, 0, 0, socket.SOL_TCP) 
      for family, socktype, proto, name, ip in addr_info: 
       if family == 2: #okay it's ipv4 
        ip, port = ip 
        processed_q.put((ip, domain)) 
       elif family == 10: #okay it's ipv6 
        ip, port, no_1, no_2 = ip 
        processed_q.put((ip, domain)) 
     except: 
      pass 
      #print 'Socket Error' 

     domains_q.task_done() 

編輯:域= domains_q.get()這條線塊,直到產品在隊列可用

問題是當我在300個線程運行此,平均負載似乎不錯,但簡單的LS -la需要5秒,一切都是緩慢的。我哪裏做錯了?我應該使用異步還是多處理?

+0

你確定空隊列異常被打破循環? – andsoa 2013-03-11 15:39:42

+0

domains_q.get()此行會阻止,直到某個項目可用,我已將其添加到帖子中。 – nacholibre 2013-03-11 15:45:35

回答

0

你真的需要300個線程並行處理300個鏈接?我從來沒有嘗試創建這麼多線程,但它可能是一個問題。這絕對不是解決問題的好方法。通常還有其他選項。首先,你不需要300個線程來監聽300個連接。創建一些似乎適用於您的硬件和操作系統的線程。使用單個線程從主隊列中檢索請求,然後將它們傳遞給thread pool中的線程。

BTW,檢查你的「從隊列中檢索」操作確實阻塞並等待如果隊列爲空。如果不是,則循環可以一直執行,而不取決於是否有傳入請求。

你可能真的需要的是一個非阻塞模式的套接字和類似select.select()等等,直到你的一個套接字準備好讀取或寫入。您可以自行編寫該代碼。如果你不急於這樣做,很可能像gevent(或twisted)良好的異步聯網庫可以幫助改善你的程序的體系結構。利用多核CPU的全功率是一個單獨的問題,但我聽說現在有辦法解決的,至少gevent(它們基於gunicorn運行多個進程;從來沒有嘗試過)。但是我認爲你遇到的問題不是執行速度,而是需要一次有效地等待許多對象的I/O。如果是這樣,爲此避免大量使用線程,但它不僅在Python中無效,而且在沒有GIL的語言中通常也是無效的,它們更適合多線程編程。 multiprocessing避免GIL,但增加了自己的執行成本,所以我建議不要在這裏使用它。