Python AsyncHTTPClient阻止我的Tornado IOLoop

Python AsyncHTTPClient阻止我的Tornado IOLoop,python,tornado,coroutine,Python,Tornado,Coroutine,你好吗 过去几天我经历了这些麻烦,我似乎无法完全理解tornado gen库 我有一段代码作为示例: @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)

你好吗

过去几天我经历了这些麻烦,我似乎无法完全理解tornado gen库

我有一段代码作为示例:

@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循环范围的增加,请求的时间也在增加

他们不应该在同一时间准备好吗

我错过什么了吗


多谢各位

AsyncHTTPClient的默认最大客户端数为10。当您启动15个请求时,其中10个请求立即开始,但其余5个请求必须等待其他请求完成后才能开始。要开始更多并发请求,请将max_客户机数量提高到更大


如果您的请求不受IO约束,那么您将不会看到太多更改。-

在编程中,我们有以下主要限制:

  • CPU(每秒可能发生的计算数)
  • 处理器中的缓存访问
  • RAM访问
  • 磁盘访问
  • 网络接入
在Python中,由于GIL,我们在CPU访问方面受到了进一步的限制。随着现代计算机趋向于多核(2、4、8或16)的发展,我们的能力进一步削弱,因为通常这些处理器的速度都会稍慢一些。有关GIL的更多信息,请查看和

为了绕过全局解释器锁,已经开发了几个回调风格的模块,如Twisted、Tornado和asyncio。这些操作的工作方式是执行一些操作,通常在到达IO停止点时放弃控制

例如,如果我正在向旋转的磁盘写入数据,也许我可以向磁盘写入100kb的数据,但当我等待写入所有信息时,也许我可以在所有数据完成写入之前进行1000次计算

或者,我可以每秒向Web服务发出100个请求,但对每个请求执行计算只需要0.0001秒。如果你看一张我在哪里度过时间的图表,它会是这样的:

    #            
    #            
    #            
    #            
    #            
    #            
    #            
    #           #
--------------------------
 reading    processing
 start    end start     end
--|--------|----|--------|------
 t=0      t=5  t=6      t=11
     start      end
 start|     end  |
--|---|------|---|-
 t=0 t=1    t=5  t=6
这些过程允许您通过发送请求数据包,然后执行其他操作,然后在某个时候返回以读取返回的数据包,来交错处理和读/写

像这样被IO束缚,你可以看到一个相当大的加速,因为不是看起来像这样:

    #            
    #            
    #            
    #            
    #            
    #            
    #            
    #           #
--------------------------
 reading    processing
 start    end start     end
--|--------|----|--------|------
 t=0      t=5  t=6      t=11
     start      end
 start|     end  |
--|---|------|---|-
 t=0 t=1    t=5  t=6
你可以得到这样的结果:

    #            
    #            
    #            
    #            
    #            
    #            
    #            
    #           #
--------------------------
 reading    processing
 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边界处是否慢

您可以很容易地使用类似于for Python的东西,并且(如果还没有)分离出您的读、处理和写函数,并查看您在哪里花费时间。如果你把大部分时间花在读函数上,那么是的,你应该看到异步方法有一个相当合理的加速。如果不是,async只会让你慢下来

1老实说,情况并没有那么糟,除非你有超高速的关键设备。然后你应该用或什么东西,把速度临界的部分,倒进C。你确实知道哪些部分是阻塞,对吗


如果您的请求不受IO限制,那么您将看不到太多更改。您能再解释一下吗?:)但是,在我的示例中,它将创建AsyncHTTPClient的不同实例,每个实例只发出一个请求。。。我错了吗?是的,在内部,AsyncHTTPClient对象共享一个请求队列。是的,我刚刚在文档中发现了这一点。太好了。Buuuut,我刚刚将max_客户端增加到50个,但仍然存在相同的问题。随着我添加更多请求,时间仍在递增。(不超过50限制)这是正确答案。我必须安装pycurl并使用以下设置:tornado.httpclient.asynchtpclient.configure(“tornado.curl\u httpclient.curlsynchtpclient”),然后一切都按预期工作。