重試,讓程式更健壯

来源:https://www.cnblogs.com/rockety/archive/2023/04/11/17306156.html
-Advertisement-
Play Games

任何通過網路與其它應用通訊地的程式,都應該有足夠的靈活性,來應對短暫的臨時性故障。因為這些故障很多時候是可以自恢復的。 例如,為了避免服務過載,很多應用會採取某些限流措施,在併發請求達到一定數量時,暫時性的拒絕新的請求加入。這種情況下,嘗試使用該應用的程式,一開始可能會被拒絕連接,但下一刻就好了。 ...


任何通過網路與其它應用通訊地的程式,都應該有足夠的靈活性,來應對短暫的臨時性故障。因為這些故障很多時候是可以自恢復的。

例如,為了避免服務過載,很多應用會採取某些限流措施,在併發請求達到一定數量時,暫時性的拒絕新的請求加入。這種情況下,嘗試使用該應用的程式,一開始可能會被拒絕連接,但下一刻就好了。

因此,在設計系統時,應該考慮到此種故障。並且在條件允許時,加入重試機制,自動再次發起相應的請求。在某些情況下,可能會顯著的改善應用程式的用戶體驗。

能否發起重試,最重要的前提之一是,對同一資源的發起多次相同的請求,能否得到相同的結果。即資源介面是否具有冪等性。

標準 REST API 中,GET/HEAD/OPTIONS 通常是不會更改伺服器上的資源的,因此大多是可重試的。

換個說法就是,如果能夠確定,下次請求有可能成功,那就可以嘗試重試。否則的話,就不必浪費時間、精力以及系統資源了。

例如,在請求 HTTP 服務時,收到 503 或 408 這樣的狀態碼,則重試可能會有效;但是如果收到了 401 或 403 之類的狀態碼,則簡單的重試肯定不起作用。

確定了什麼情況下發起重試後,還有另外一個問題值得考慮。即在什麼時間、以什麼樣的頻率發起重試。儘管可以,但通常並不會是請求失敗後,立即發起重試,而是需要根據具體的場景,選擇合適的重試
時機。

假如說我們請求失敗的原因,是服務端請求過載。則立即發起重試,除了給服務端添亂外,不會有其它結果。嚴重情況下,可能會加劇伺服器的負擔,直到耗盡伺服器資源。

為了避免上述問題,常見的做法是在重試之前增加一些延遲。但是如何增加這些延遲,又有多種策略,比較多使用的有兩種:

  • 固定間隔。即每次請求失敗後,都等待固定的時間後,再次發起下次重試請求;
  • 指數遞增。即多次請求之間的延時,成倍增加;

如果失敗是由服務端過載引起的,則後一種策略可能會更好。假如它的初始請求在 0ms 發出,則第二次請求在失敗 200ms 後發出,第三次請求在失敗 400ms 後發出,第四次在 800ms... 以此類推。這種分散的請求和重試機制,可能有助於減緩客戶端及伺服器的負載,提高我們最終獲取到成功結果的機會。

但是假如所有的請求都從同一時刻發起,並按照同樣的機制延時重試,則兩種策略是一樣的,並不會有所改進。這種情況下,可能需要加入一些隨機因素。

扯的有點多,接下來搞些實際的,上一點兒代碼。簡單起見,這裡演示一下在 JavaScript 中的實現,使用諸位都瞭解的 axios。Axios 提供了攔截器機制,用來處理通用的重試邏輯正合適。

const SLEEP_TIME = 200;
const RETRY_TIMES = 3;
const RETRY_STATUS = [408, 503, 504];

function getSleepTime(i = 0) {
  const wTime = Math.min(SLEEP_TIME * 2 ** i);
  return Math.random() * wTime;
}

async function fakeSleep(ms) {
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, ms);
  });
}

async function onError(error) {
  const { status } = error.response;
  let { retryCount = 0 } = error.response.config;

  if (RETRY_STATUS.includes(status) && retryCount < RETRY_TIMES) {
    retryCount += 1;
    sleep_ms = getSleepTime(retryCount);
    await fakeSleep(sleep_ms);

    error.config.retryCount = retryCount;
    return await axios(error.config);
  }
}

axios.interceptors.response.use(onError);

代碼不多,應該不需要額外的解釋。其它編程語言,實現思路大致也差不多。相信您肯定可以寫出更好的。

歡迎批評指正。

作者:袁首京

原創文章,轉載時請保留此聲明,並給出原文連接。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Redis 是一個高性能的鍵值存儲系統,支持多種數據結構。 包含五種基本類型 String(字元串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),和三種特殊類型 Geo(地理位置)、HyperLogLog(基數統計)、Bitmaps(點陣圖)。 ...
  • 最近在閱讀《認知覺醒》這本書,裡面有句話非常打動我:通過自己的語言,用最簡單的話把一件事情講清楚,最好讓外行人也能聽懂。希望藉助今天這篇文章,能用大白話說清楚這個相對比較底層和複雜的MVCC機制 ...
  • 二手車交易的核心問題在於車況信息不透明。中國二手車交易市場制度尚不完善,長期以來缺少行業公認的車輛估值標準和車況檢測標準,二手車商提供的估值和車況信息不夠透明。這導致用戶和車商交易雙方都陷入了迴圈困境:用戶對車商信任不足,購買意願低。二手車商缺少潛在客戶線索,為招攬客戶不惜採用虛假信息,使得市場環境... ...
  • 華為運動健康服務(HUAWEI Health Kit)6.10.0 版本新增的能力有哪些? 閱讀本文尋找答案,一起加入運動健康服務生態大家庭! 一、 支持三方應用查詢用戶測量的連續血糖數據 符合申請Health Kit服務中開發者申請資質要求的企業開發者,可申請訪問用戶的心率、壓力、血糖等健康數據。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 CSS是有魔法的,我們今天來實現一個CSS的動畫效果,只需要幾行代碼就可以搞定。 第一步、我們要將一行文字從中間展開 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
  • 本文旨在通過部署微前端項目的實踐過程中沉澱出一套部署方案,現就一些重點步驟、碰到的問題做了一些總結。 ...
  • 大致思路: 使用相對定位的div覆蓋文本內容,並用animation控制寬度,位置。 換行步驟在外層div上控制高度即可。 css的steps與animation一起使用可以控制文字單個顯示,類似於文本輸入,不過顯示頻率是線性。 添加一些css變數控制步驟寬度、高度和時間等,便於vue中也通過組件的 ...
  • [ 點擊 👉 關註「 全棧工程師修煉指南」公眾號 ] 設為「⭐️ 星標」帶你從基礎入門 到 全棧實踐 再到 放棄學習! 涉及 網路安全運維、應用開發、物聯網IOT、學習路徑 、個人感悟 等知識分享。 希望各位看友多多支持【關註、點贊、評論、收藏、投幣】,助力每一個夢想。 【WeiyiGeek Bl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...