requests請求超時嘗試重連的3種方式


參考文檔

https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#module-urllib3.util.retry
https://blog.csdn.net/shengruxiahua2571/article/details/103165315/

了解

連接超時 ==> 發起請求連接到建立連接之間的最大時長
讀取超時 ==> 連接成功開始到服務器返回響應之間等待的最大時長

代碼示例

import traceback
import time
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
retries = Retry(total=3,
                        backoff_factor=0.1,
                        status_forcelist=[ 500, 502, 503, 504 ])
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=retries))
s.mount('https://', HTTPAdapter(max_retries=retries))
count = 0
while True:
    if count < 3:
        try:
            file = s.get(url, stream=True, timeout=5)
            return file.content
        except:
            print('Retry!')
            time.sleep(3)
            traceback.print_exc()
            count += 1
            continue
    else:
        print('Fail!')
        break
    
# 相關Retry參數說明
total  允許的重試次數
connect 要重試的連接相關錯誤數
read  讀取錯誤時重試多少次
redirect  要執行的重定向數
status_forcelist 一組我們應該強制重試的HTTP狀態代碼
backoff_factor 在第二次嘗試后在嘗試之間應用的退避因素(大多數錯誤會立即通過第二次嘗試解決,沒有延遲)
raise_on_redirect  如果重定向次數用盡,是否引發 MaxRetryError 或返回響應代碼在 3xx 范圍內的響應。
raise_on_status  類似於raise_on_redirect:如果狀態在status_forcelist范圍內並且重試已經用盡,我們是否應該引發異常或返回響應。

結合項目需求使用的兩種方法

方法一,普通循環請求判斷

    def connection_demo(self, request):
        start_time = datetime.now()
        while True:
            ...  # 省略其它代碼部分
                num_times = 0
                session = requests.Session()   # 推薦使用session可以提高訪問速度
                while num_times < 3:
                    try:
                        result = session.get(url=url, verify=False, timeout=5)
                        if result.status_code == 200:
                            break
                    except requests.exceptions.RequestException:  # 如果HTTP請求返回了不成功的狀態碼, Response.raise_for_status() 會拋出一個 HTTPError 異常
                        num_times += 1
                        continue
                if num_times < 3:
                    break
                else:
                    raise VtuneTimeOutException
            ...  # 省略其它代碼部分
        return redirect_url

方法二,requests的retry

import requests
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter

def connection_demo(self, request):
    start_time = datetime.now()
    while True:
       ... # 省略其余代碼部分
            req = requests.Session()
            retries = Retry(total=3,
                            backoff_factor=0.1,
                            status_forcelist=[500, 502, 503, 504])
            req.mount('https://', HTTPAdapter(max_retries=retries))
            try:
                result = req.get(url=url, verify=False, timeout=5)
                if result.status_code == 200:
                    break
                else:
                    raise VtuneTimeOutException
            except requests.exceptions.RequestException:
                raise VtuneTimeOutException
        ... # 省略其余代碼部分
    return redirect_url

方法3,裝飾器retry

pip install retry
自行百度

總結

需求是:后端視圖代碼請求由內部生成並存儲到數據庫中的一個url,看是否通再將url返回給前端,3次重連,根據requests的status_code為200來判斷是否成功,
狀態碼200成功則結束,其它狀態碼不成功則繼續,
並且在3次重連內,有超時等問題都不希望讓其拋出錯誤,等3次重連結束后,再判斷是否都不成功再拋出錯誤。使用第二種方法有點小bug,
具體還是要結合項目,之前沒有加status_forcelist這個玩意,導致有一次請求得到503,頁面報錯了,但是因為有三次重連的機制,
報錯了還繼續執行成功了。所以后面加了status_forcelist,但是還有異常捕獲的問題,因為只要有一次超時或其它問題,
都會被捕獲拋異常,那樣也會遇到報錯了還繼續執行成功了的問題。
所以我使用了第一種方式寫法,當然了還是要結合項目需求來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM