使用多线程处理的python请求

使用多线程处理的python请求,python,multithreading,python-requests,Python,Multithreading,Python Requests,我正在创建一个HTTP客户端,它每秒可以生成数百个连接,并在每个连接上发送多达10个请求。我使用线程,因此可以实现并发性。 这是我的密码: def generate_req(reqSession): requestCounter = 0 while requestCounter < requestRate: try: response1 = reqSession.get('http://20.20.1.2/tempurl.html')

我正在创建一个HTTP客户端,它每秒可以生成数百个连接,并在每个连接上发送多达10个请求。我使用线程,因此可以实现并发性。 这是我的密码:

def generate_req(reqSession):
    requestCounter = 0
    while requestCounter < requestRate:
        try:
            response1 = reqSession.get('http://20.20.1.2/tempurl.html')
            if response1.status_code == 200:
                client_notify('r')
        except(exceptions.ConnectionError, exceptions.HTTPError, exceptions.Timeout) as Err:
            client_notify('F')
            break
        requestCounter += 1

def main():
    for q in range(connectionPerSec):
        s1 = requests.session()
        t1 = threading.Thread(target=generate_req, args=(s1,))
        t1.start()
def生成请求(请求会话):
requestCounter=0
当requestCounter
问题:

  • 当requestRate=1时,它不会扩展到200个连接/秒以上。我在同一台客户机上针对服务器运行了其他可用的HTTP客户机,测试运行良好,并且能够扩展

  • 当requestRate=10时,连接数/秒降至30。 原因:无法每秒创建目标数量的线程

  • 对于问题2,客户端计算机无法创建足够的请求会话并启动新线程。一旦requestRate设置为大于1,事情就开始分崩离析。 我怀疑这与请求使用的HTTP连接池有关


    请指出我在这里做错了什么。

    我无法将事情分解,但是以下代码有一些新功能:

    1) 扩展日志记录,包括特定的每线程信息

    2) 所有线程
    join()

    3) 多线程
    打印
    倾向于交错消息,这可能会很麻烦。此版本使用
    yield
    ,因此将来的版本可以接受消息并清晰地打印它们

    来源
    为什么要重用相同的
    会话
    对象?据我所知,您的
    connectionPerSec
    实际上意味着并行线程的数量,而
    requestRate
    实际上是每个线程上的串行请求数量。您可能还想看看。session对象仅在生成的线程中重用,因此它对所有串行请求使用相同的连接。似乎concurrent.futures中的ThreadPoolExecutor执行了与我尝试执行的相同的操作?请注意,在CPython中,线程的并发性是有限的:一次只有一个线程可以执行Python字节码。全局解释器锁强制执行此限制,以简化内存管理。
    import exceptions, requests, threading, time
    
    requestRate = 1
    connectionPerSec = 2
    
    
    def client_notify(msg):
        return time.time(), threading.current_thread().name, msg
    
    def generate_req(reqSession):
        requestCounter = 0
        while requestCounter < requestRate:
            try:
                response1 = reqSession.get('http://127.0.0.1/')
                if response1.status_code == 200:
                    print client_notify('r')
            except (exceptions.ConnectionError, exceptions.HTTPError, exceptions.Timeout):
                print client_notify('F')
                break
            requestCounter += 1
    
    def main():
        for cnum in range(connectionPerSec):
            s1 = requests.session()
            th = threading.Thread(
                target=generate_req, args=(s1,),
                name='thread-{:03d}'.format(cnum),
            )
            th.start()
    
        for th in threading.enumerate():
            if th != threading.current_thread():
                th.join()
    
    
    if __name__=='__main__':
        main()
    
    (1407275951.954147, 'thread-000', 'r')
    (1407275951.95479, 'thread-001', 'r')