2016-07-14 67 views
1

你好嗎?AsyncHTTPClient阻止我的龍捲風IOLoop

我在最後的日子裏經歷過這個麻煩,我似乎無法完全理解龍捲風基因庫。

我有這樣的一段代碼,作爲一個例子:

@gen.coroutine 
def get(self, build_id=None): 
    status_query = self.get_query_arguments("status") 
    limit_query = self.get_query_arguments("limit") 

    results = [self._dummy() for i in range(15)] 
    yield results 

def _dummy(self): 
    http_client = tornado.httpclient.AsyncHTTPClient() 
    return http_client.fetch("https://www.google.com", headers=self.headers, validate_cert=False) 

,因爲我以爲,我的15個請求獲取谷歌應該幾乎在同一時間被觸發。 「結果」列表應該是期貨清單,然後,產生清單應該等待所有清單完成。

這實際上正在發生,但需要大約6秒才能完成這些請求,並且隨着我增加for循環的範圍而逐漸增加。

他們不應該在同一時間準備好嗎?

我錯過了什麼嗎?

非常感謝!

+0

如果你的請求沒有IO綁定,那麼你不會看到太多的改變。 –

+0

你能解釋我多一點嗎? :) –

回答

2

AsyncHTTPClient的默認max_clients爲10.當您發起15個請求時,其中10個立即開始,但其餘5個必須等待其他請求完成才能開始。要開始更多的併發請求,請將max_clients提高到更大的數量。 See Tornado's documentation for details on configuring AsyncHTTPClient.

+0

但是,正如它在我的例子中,將創建AsyncHTTPClient不同的情況下,每一個決策只是一個請求......難道我錯了嗎? –

+0

是 - 內部,AsyncHTTPClient對象共享請求中的一個隊列。 –

+0

是的,我剛剛在文檔中發現。那很棒。 Buuuut,我剛剛將max_clients增加到了50,並且仍然有相同的問題。隨着我添加更多請求,時間依然在遞增。 (不超過50限制) –

1

如果你的請求沒有IO綁定,那麼你不會看到太多的改變。 - Me

在編程這些是我們具有初級限制:

  • CPU(計算的數目,可以每秒發生)在處理器
  • 緩存訪問
  • RAM訪問
  • 磁盤訪問
  • 網絡訪問

在Python中,由於GIL,我們甚至進一步限制了CPU訪問。由於趨向於多核 - 2,4,8或16的計算機,我們甚至進一步癱瘓,因爲通常是,這些處理器中的每一個都會慢一點。有關GIL的更多信息,請查看David Beazley's GIL talkLarry Hasting's GIL-ectomy

爲了繞過Global Interpreter Lock,開發了幾個回調式模塊,如Twisted,Tornado和asyncio。這些工作的方式是通過執行一些操作,當它們到達IO停止點的時候,通常會產生控制權。

例如,如果我正在將數據寫入旋轉磁盤,也許我可以寫入100kb的磁盤,但在等待所有信息寫入時,或許我可以關閉並執行1,000次在所有數據寫完之前進行計算。

或者,也許我可以讓每秒100個請求Web服務,但是隻需要我0.0001s執行我的計算爲每個請求。如果你看的,我把我的時間它會是這個樣子的圖形:

#    
    #    
    #    
    #    
    #    
    #    
    #    
    #   # 
-------------------------- 
reading processing 

什麼這些過程讓你做的是通過發送交錯處理和讀/寫,請求報文關閉,然後做其他事情,然後在某個時候回來讀取返回的數據包。

被IO約束這樣,你可以看到一個非常龐大的加速,因爲而不是尋找這樣的事情:

start end start  end 
--|--------|----|--------|------ 
t=0  t=5 t=6  t=11 

你可以得到這樣的事情:

 start  end 
start|  end | 
--|---|------|---|- 
t=0 t=1 t=5 t=6 

如果你的過程是CPU限制,你不會看到任何加速(或者至少沒有多少),因爲你花費30多歲做處理只有1秒做任何形式的等待網絡。

嘗試異步方法之前,給標準的單線程方式,看看1),如果它的速度不夠快; 2)如果在網絡/ IO邊界很慢。

您可以輕鬆使用類似Python的line profiler之類的東西,並且(如果還沒有的話)分離出讀取,處理和寫入功能,並查看您花費的時間。如果你花大部分的在讀功能的時間,那麼是的,你應該看到從異步方法相當合理的增速。如果不是,異步會讓你放慢速度。

老實說這不是真的那麼糟糕,除非你有超高速的關鍵。然後你應該使用cffi或其他東西來把速度關鍵部分,並將它們轉儲到C.你沒有找出哪些部分是保留,對嗎?

+0

回答 – desertkun