2013-12-23 60 views
1

我有兩個requesthandler。一個提供大量的auf數據,另一個只有少數幾個數據集。龍捲風:是BaseHandler.write阻塞?

class HugeQueryHandler(BaseHandler): 
    @gen.coroutine 
    def get(self): 
     try: 
      cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM huge_table;') 
      for row in cursor: 
       self.write('Query results: {} <br />'.format(row)) 
     except Exception as error: 
      self.write(str(error)) 

     self.finish() 

class SmallQueryHandler(BaseHandler): 

    @gen.coroutine 
    def get(self): 
     try: 
      cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM small_table;') 
      for row in cursor: 
       self.write('Query results: {} <br />'.format(row)) 
     except Exception as error: 
      self.write(str(error)) 

     self.finish() 

我的問題

是對循環阻塞的迴應?當我請求巨大的處理程序調用後的少量數據時,我必須等待,第一個完成...

回答

0

write()不會在網絡上阻塞(它只是附加到緩衝區) ,但是你不會在任何地方屈服,所以整個循環必須在任何其他任務可以運行之前完成。我認爲問題不是寫入,而是迭代 - 「對於遊標中的行」不會產生任何結果,所以無論是momoko緩存了整個結果集還是存儲在內存中,或者在從數據庫中讀取數據時都是阻塞的。如果是後者,則需要以非阻塞的方式訪問遊標。如果是前者,那麼除了將查詢分解爲更小的塊之外,您可以做的並不多。 (你可以偶爾在循環中調用「yield gen.Task(self.flush)」,但這會延長整個數據緩衝在內存中的時間,因此可能不是明智的)。

0

所以,這就是關鍵。 for循環需要完成。

這是怎麼回事?

class HugeQueryHandler(BaseHandler): 

    executor = tornado.concurrent.futures.ThreadPoolExecutor(1) 

    @tornado.concurrent.run_on_executor 
    def generate_response(self, cursor): 
     return "<br />".join("{}".format(row) for row in cursor) 

    @tornado.web.asynchronous 
    @gen.engine 
    def get(self): 
     try: 
      cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM huge_table;') 
      res = yield self.generate_response(cursor) 
      self.write(res) 
     except Exception as error: 
      self.write(str(error)) 
     self.finish()