python3 解決requests出錯重試的問題

對python3下的requests使用並不是很熟練,今天稍微用瞭下,請求幾次下來後發現出現連接超時的異常,上網查瞭下,找到瞭一個還算中肯的解決方法。

retrying是python的一個自帶的重試包

導入方式:

from retrying import retry

簡單使用

retrying 這個包的用法原理就是在你不知道那段代碼塊是否會發生異常,若發生異常,可以再次執行該段的代碼塊,如果沒有發生異常,那麼就繼續執行往下執行代碼塊

以前你的代碼可能是這樣寫的:

def get_html(url):
 pass
def log_error(url):
 pass
url = ""
try:
 get_page(url)
except:
 log_error(url)

也有可能是這樣子寫的:

# 請求超過十次就放棄
attempts = 0
success = False
while attempts < 10 and not success:
 try:
  get_html(url)
  success = True
 except:
  attempts += 1
  if attempts == 10:
   break

使用 retrying 的寫法:

import random
from retrying import retry
@retry()
def do_something_unreliable():
 if random.randint(0, 10) > 1:
  raise IOError("Broken sauce, everything is hosed!!!111one")
 else:
  return "Awesome sauce!"
result = do_something_unreliable()
print(result)

上面的是簡單的用法,你可以試下,下面是一些可選參數的使用方式。

stop_max_attempt_number

用來設定最大的嘗試次數,超過該次數就停止重試

stop_max_delay

超過時間段,函數就不會再執行瞭

wait_random_min和wait_random_max

用隨機的方式產生兩次retrying之間的停留時間

補充:python中Requests的重試機制

requests原生支持

import requests
from requests.adapters import HTTPAdapter
s = requests.Session()
# 重試次數為3
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))
# 超時時間為5s
s.get('http://example.com', timeout=5)

requests使用的重試算法:BackOff(指數退避算法)

什麼是指數退避算法

在wiki當中對指數退避算法的介紹是:

In a variety of computer networks, binary exponential backoff or truncated binary exponential backoff refers to an algorithm used to space out repeated retransmissions of the same block of data, often as part of network congestion avoidance.

翻譯成中文的意思大概是“在各種的計算機網絡中,二進制指數後退或是截斷的二進制指數後退使用於一種隔離同一數據塊重復傳輸的算法,常常做為網絡避免沖突的一部分”

比如說在我們的服務調用過程中發生瞭調用失敗,系統要對失敗的資源進行重試,那麼這個重試的時間如何把握,使用指數退避算法我們可以在某一范圍內隨機對失敗的資源發起重試,並且隨著失敗次數的增加長,重試時間也會隨著指數的增加而增加。

當然,指數退避算法並沒有人上面說的那麼簡單,想具體瞭解的可以具體wiki上的介紹

當系統每次調用失敗的時候,我們都會產生一個新的集合,集合的內容是0~2n-1,n代表調用失敗的次數

第一次失敗 集合為 0,1

第二次失敗 集合為 0,1,2,3

第三次失敗 集合為 0,1,2,3,4,5,6,7

在集合中隨機選出一個值記為R,下次重試時間就是R*基本退避時間(對應在指數退避算法中爭用期) 當然,為瞭防止系統無限的重試下去,我們會指數重新的最大次數

為什麼要使用指數退避算法

使用指數退避算法,可以防止連續的失敗,從某方面講也可以減輕失敗服務的壓力,試想一下,如果一個服務提供者的服務在某一時間發生瞭異常、超時或是網絡抖動,那麼頻繁的重試所得到的結果也大致都是失敗。這樣的頻繁的重試不僅沒有效果,反而還會增服務的負擔。

應用場景有哪些

接入三方支付服務,在三方支付提供的接入接口規范中,服務方交易結束結果通知和商戶主動查詢交易結果都用到重發機制

在app應用中,很多場景會遇到輪詢一類的問題,輪詢對於app性能和電量的消耗都過大。

代碼示例

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。

推薦閱讀:

    None Found