以前對於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/
