【原创】python requests 库底层Sockets处于close_wait状态

时间:2022-10-16 09:02:43

以前对于Requests库只是简单是使用,在现在公司的后台中,有多个接口是直接使用requests.get .post之类的方法来做的,进行过一段时间的压力测试,发现性能低的可怜,且linux服务器有好多CLOSE_WAIT状态,所以这个问题不解决是没办法上线的。

  解决办法参考以下方法(下文附连接):

    第一篇说了:requests 库自己会处理好连接池的问题,且访问完成之后是会有SOCKET 的CLOSE_WAIT状态,这个是正常的,后续会直接复用这些连接(CLOSE_WAIT状态直接使用在多线程环境下不会复用,这里是一个大坑,下文第三篇说明了解决办法),但值得注意的是CLOSE_WAIT状态如果非常多,且一直存在,就需要思考哪里出了问题,可能因为并发太高出错,或者没有调用resp.close方法,因为没有读取完响应是不会释放连接的。

    第二篇说了:直接.get .post得不到任何好处,因为每次他都会创建一个连接池,而这个连接池你却只用了一次。所以,如果想要用requests库的连接池功能,需要使用全局session,且自己构造好HttpAdapter实例,session.mount上就可以了,并发大的时候才会有效果。

    第三篇说了:使用连接池的时候不是任何时候都有效,仅当你使用了多线程之类的并发才有效果,如果你是单线程的,那么你将不会得到连接池的任何好处,因为单线程里面是串行的,就是说一个线程对应一个连接。此外,里面还说了HttpAdapter的俩个参数的含义:pool_connections, 是指你的后台程序最多连接多少个不同的主机;pool_maxsize, 是指针对每个主机你能创建的连接最大有多少个(底层TCP)。注,这里不是初始多少个和最大多少个的意思!!!

    pool_maxsize针对不同的HOST,每个HOST是独立的连接池,所以如果我们后台程序连接了多台服务器,用pool_connections参数指定最大个数,pool_maxsize指定每个后台主机最大多少个链接,且又由于一个线程一个连接的因素,因此我们服务器程序有多少个线程pool_maxsize就指定多少。

  注,由于http解析较慢,后台服务器之间不应使用它作为服务器之间的通信协议,但这是前人的基础上改的,没办法,只能逐步优化。

  此外,改善完之后,性能增长增长不是很明显,且发现CPU占用率不高,此时可以增加进程数和线程数来提高并发数和用户请求等待时间,因为这很可能是因为我们的后台程序是严重的IO密集型应用,大部分时间都在等待,例如等待http响应

参考:

https://github.com/kennethreitz/requests/issues/1973

https://blog.hubert.tw/2014/02/08/use-connection-pool-in-python-requests/

https://laike9m.com/blog/requests-secret-pool_connections-and-pool_maxsize,89/