Python 为什么多进程无法通过eventlet加速发送HTTP请求

Python 为什么多进程无法通过eventlet加速发送HTTP请求,python,python-multiprocessing,eventlet,Python,Python Multiprocessing,Eventlet,我有一个应用程序可以发送一堆HTTP请求。首先,我使用eventlet和请求来实现它。但是性能太低了。因此,我希望使用多进程加速它。需要知道的是,服务器处理单个请求(不包括网络传输)大约需要200ms 但是,多进程比原始版本慢。我对这个结果感到非常惊讶!为什么? 代码如下所示,我使用timeit来测量时间 import eventlet eventlet.monkey_patch(all=False, socket=True) import requests URL = 'http://..

我有一个应用程序可以发送一堆HTTP请求。首先,我使用eventlet请求来实现它。但是性能太低了。因此,我希望使用多进程加速它。需要知道的是,服务器处理单个请求(不包括网络传输)大约需要200ms

但是,多进程比原始版本慢。我对这个结果感到非常惊讶!为什么?

代码如下所示,我使用timeit来测量时间

import eventlet
eventlet.monkey_patch(all=False, socket=True)

import requests

URL = 'http://....'

def send():
    pile = eventlet.GreenPile(20)
    for x in xrange(100):
        pile.spawn(requests.get, URL)
    for x in pile:
        pass

import multiprocessing

def main():
    procs = [multiprocessing.Process(target=send) for _ in range(3)]
    for p in procs:
        p.start()
    for p in procs:
        p.join()

import timeit

if __name__ == '__main__':
    print timeit.timeit(main, number=1)

TL;医生:没有足够的信息纯粹的推测,服务器是限制因素(这可能是人为限制或资源匮乏造成的),因此通过添加更多并发请求,平均而言,会使每个请求的速度变慢

这里有一种解释方法:客户端和服务器上的资源量都是有限的:每次CPU周期、每次内存访问、内存大小、网络带宽。OS和eventlet合理地利用了这些资源。这样,您就可以估计发出单个请求所需的资源量,软件将以合理的模式(接近线性)扩展它。要从多处理中获益,需要客户端进程使单个CPU单元100%繁忙。具体来说,
请求
库善于浪费硬件资源,在我尝试过的所有方法(httplib、httplib2、urllib)中,它产生的CPU开销最多。但是,您必须发出大量(数千)并发请求,或者CPU非常糟糕/繁忙,以使其成为瓶颈

准确答案需要信息:

  • HTTP客户端和服务器是否对任何资源一致?即,它们是否在相同的物理硬件上运行
  • 在单进程模式下,您能够生成的最大请求频率(每秒计数)是多少?调整绿桩大小以改变并发请求的数量
  • 使用多个进程生成请求的最大频率是多少?调整绿堆大小和进程数。尝试运行几个独立的Python解释器而不进行多处理
  • 服务器是瓶颈吗?通过在单独的硬件上添加另一个客户端进行检查。如果请求频率较高,则服务器不是瓶颈。如果请求频率随着更多客户端的增加而下降,那么服务器已经在极限运行,多处理只会让事情变得更糟
  • 请求时间分布是什么?在220/300/400/500/1000/毫秒或更长时间内完成请求的百分比是多少
  • 什么是网络延迟/带宽?请求/响应大小是多少?那你的网络饱和了吗
回答这些问题将使您对客户端/服务器内部和之间发生的事情有极好的直觉


相关Github问题:

我还没有对代码进行充分的推理,但您使用的是
多处理
,它在创建进程方面有着昂贵的前期成本,但允许多个内核在I/O受限的问题上并行执行计算。只要瓶颈纯粹是I/O,线程可能是更好的解决方案。@zehnpaard,我也尝试过多线程,结果与多进程相同。对这样的结果有什么想法吗?实际上
eventlet.GreenPile
spawn
创建了绿色线程,因此在
eventlet
之上使用线程或进程可能是重复的。对服务器的I/O请求已经被并行处理。@zehnpaard,这是否意味着即使多个进程也将共享内核提供的单个IO循环?不,这是相反的问题-即使在原始代码中,当您不使用
多处理时,
eventlet
模块已经为您提供了并发I/O,因此,使用另一种并发模式(无论是进程还是线程)没有帮助。谢谢您的回复。我一个接一个地回答了问题。服务器和客户端位于不同的位置。2.无论绿堆大小为10、20或200,发送固定数量请求所用的时间几乎相同。3.服务器可以在一秒钟内接受更多请求。我使用ApacheAB测试它,ab的运行速度比eventlet版本快10倍。4.不确定。请求/响应大小小于256字节。需要说明的是,这是HTTPS协议。@Jacky请使用不同的池大小进行以下测试:运行100-1000个请求,并从开始到结束测量客户端进程的CPU使用率。如果不确定如何测量CPU使用率,可以使用eventlet测试中的GNU time(通常安装为/usr/bin/time)或CPU_使用率函数