最近在用requests寫一些項目,遇見了一些問題,百度了很多,有些都不太好使,最后看了下requestsAPI文檔,才明白了很多,最后項目趨于穩定。看來學東西還是API文檔比較權威啊~
問題場景
項目需要通過一臺主機搭上代理向目標服務器定時交換數據,主機上同時跑著比較占用資源的其他項目。
項目設計思路
因為主機上已經運行了比較占用線程內存資源的其他項目,所以計劃本項目就應該在不能太占用資源,的前提下保持比較流暢的運行。
設計了在線程下加上定時器的思路,定時運行相關網絡請求方法。
請求量 :每隔5秒鐘,發送10 ~ 30個請求。
核心代碼
headers = {"Content-Type": "application/json;charset=uf8"}
url = config.baseurl + path
try:
response = requests.post(url, data= data, headers=headers ,stream= False,timeout= 10)
except Exception as indentfier:
time.sleep(5)
getLoaclObjs(False)
par = json.loads(data)
if response != None:
print(" method name = ", par["IPCType"],"\n sendData = ",json.dumps(par), "\n response.state.code = ",response.status_code,"\n response.text = ",response.text,"\n\n", url, "\n\n")
問題:
報錯:
HTTPConnectionPool(host='172.19.5.101', port=8085): Max retries exceeded with url: <url >(Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x006DB1F0>, 'Connection to <server ip> timed out. (connect timeout=10)'))
分析:
報錯的重點在于 connect timeout
解決方案
1.由于是timeout的報錯,所以為了項目穩定首先要做的就是做好重連操作,在代碼中其實已經做好了 try ... except 中 except中為錯誤處理。再次調用了方法。
2.處理過后數據交互沒有了毛病,但是報錯仍然頻繁,甚至后邊有了新的錯誤:
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionAbortedError(10053, '你的主機中的軟件中止了一個已建立的連接。', None, 10053, None))
度娘和overflow都告訴我添加一下代碼:
#設置重連次數
requests.adapters.DEFAULT_RETRIES = 15
# 設置連接活躍狀態為False
s = requests.session()
s.keep_alive = False
基本上意思就是發出的網絡請求比較頻繁,requests內置的urllibs3不能及時的為我們斷開連接,于是就有了以上報錯。
代碼的基本意思就是斷開連接、增加重試次數。
headers = {"Content-Type": "application/json;charset=uf8"}
url = config.baseurl + path
try:
#設置重連次數
requests.adapters.DEFAULT_RETRIES = 15
# 設置連接活躍狀態為False
s = requests.session()
s.keep_alive = False
response = requests.post(url, data= data, headers=headers ,stream= False,timeout= 10)
except Exception as indentfier:
time.sleep(5)
getLoaclObjs(False)
par = json.loads(data)
if response != None:
print(" method name = ", par["IPCType"],"\n sendData = ",json.dumps(par), "\n response.state.code = ",response.status_code,"\n response.text = ",response.text,"\n\n", url, "\n\n")
還有別的處理方法就是增加代理,由于主機是用代理的,所以項目換別的代理就不太現實,否則有可能直接連接不上目標服務器。
于是想到了直接管理內存,文檔上是這么表述的:
好消息——歸功于 urllib3,同一會話內的持久連接是完全自動處理的!同一會話內你發出的任何請求都會自動復用恰當的連接!
注意:只有所有的響應體數據被讀取完畢連接才會被釋放為連接池;所以確保將 stream 設置為 False 或讀取 Response 對象的 content 屬性。
也就是說除非stream=False或者response.content /response.text被操作,不然該請求不會被釋放。
同其他的自動管理內存的語言一樣,不論垃圾回收還是引用計數,都存在一個問題就是內存釋放比較緩慢,于是我就在代碼中手動關閉了連接。
headers = {'Content-Type': "application/json;charset=uf8"}
url = baseurl + path
response = None
try:
#設置重連次數
requests.adapters.DEFAULT_RETRIES = 5
s = requests.session()
# 設置連接活躍狀態為False
s.keep_alive = False
response = requests.post(url, data=data, headers=headers,stream=False,timeout= 10)
# 關閉請求 釋放內存
response.close()
del(response)
except Exception as indentfier:
time.sleep(5)
timer = threading.Timer(timerFlag, upload_position)
timer.start()
最終有效減少了報錯次數。
__End ~
? ?
? ?
? ?
親情鏈接:
個人網站