摘要:再次使用方式請求,再分別查看和兩個端口號對應的服務日志,可以發(fā)現(xiàn)只有一個服務收到請求。常見的請求方法中,是冪等的,而是非冪等的。而一般對應,如果執(zhí)行多次后,可能會造成數(shù)據(jù)重復插入的問題。
Nginx通過反向代理做負載均衡時,如果被代理的其中一個服務發(fā)生錯誤或者超時的時候,通常希望Nginx自動重試其他的服務,從而實現(xiàn)服務的高可用性。實際上Nginx本身默認會有錯誤重試機制,并且可以通過proxy_next_upstream來自定義配置。
如果不了解HTTP協(xié)議以及Nginx的機制,就可能在使用過程中遇到各種各樣的坑。例如服務出現(xiàn)了錯誤或超時卻未重試,或者一些例如創(chuàng)建訂單或發(fā)送短信這類的HTTP接口,客戶端只發(fā)送一次請求,后臺卻由于Nginx重試導致創(chuàng)建了多個訂單,或者收到多條短信,導致一些業(yè)務上的問題。
proxy_next_upstream在Nginx配置文件中,proxy_next_upstream用于指定在什么情況下Nginx會將請求轉移到其他服務器上。其默認值是proxy_next_upstream error timeout,即發(fā)生網(wǎng)絡錯誤以及超時,才會重試其他服務器。默認情況下服務返回500狀態(tài)碼是不會重試的,如果想在響應500狀態(tài)碼時也進行重試,可以配置:
proxy_next_upstream error timeout http_500;
當然還有http_502、http_503、http_404等可以指定在出現(xiàn)哪些狀態(tài)碼的情況下需要重試。具體配置項可以參考官方文檔: http://nginx.org/en/docs/http... 。
用一個最簡單的例子來測試一下該特性,例如下面是Spring Boot寫了一個簡單的HTTP接口,返回500狀態(tài)碼:
@SpringBootApplication public class NginxRetryApplication { public static void main(String[] args) { SpringApplication.run(NginxRetryApplication.class, args); } } @RestController class TestController { @RequestMapping("/") public String test() { System.out.println("收到一個請求"); // 打印日志 throw new RuntimeException(); // 拋出異常, 返回500狀態(tài)碼 } }
分別使用9030和9031兩個端口號啟動該Spring Boot服務,然后Nginx配置好負載均衡:
upstream nginxretry { server 127.0.0.1:9030 max_fails=0; server 127.0.0.1:9031 max_fails=0; } server { listen 9039; location / { proxy_pass http://nginxretry; proxy_next_upstream error timeout http_500; } }
注意:以上配置中max_fails=0是為了更方便的測試Nginx錯誤重試機制。max_fails默認值是1,用于指定一個server在一段時間內(默認10s)發(fā)生錯誤次數(shù)達到多少次,Nginx就會自動將該服務器下線。這里設置為0是禁用這個特性,防止在測試過程中服務器被踢下線不好測試。線上環(huán)境下一般不會設置max_fails=0。
配置完成后重啟Nginx,使用GET方式請求 http://localhost:9039/ ,再分別查看9030和9031兩個端口號對應的服務日志,可以發(fā)現(xiàn)兩個服務都收到請求,也就是Nginx在訪問其中一個服務收到500錯誤狀態(tài)碼后,又嘗試去訪問另一個服務。
再次使用POST方式請求 http://localhost:9039/ ,再分別查看9030和9031兩個端口號對應的服務日志,可以發(fā)現(xiàn)只有一個服務收到請求。也就是當請求類型是POST時,Nginx默認不會失敗重試。如果想讓POST請求也會失敗重試,可以繼續(xù)向下閱讀。
non_idempotent在Nginx文檔中可以看到proxy_next_upstream有一個選項non_idempotent:
normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to the next server if a request has been sent to an upstream server (1.9.13); enabling this option explicitly allows retrying such requests;
通常情況下,如果請求使用非等冪方法(POST、LOCK、PATCH),請求失敗后不會再到其他服務器進行重試。加上non_idempotent選項后,即使是非冪等請求類型(例如POST請求),發(fā)生錯誤后也會重試。
如果想讓POST請求也會失敗重試,需要配置non_idempotent:
upstream nginxretry { server 127.0.0.1:9030 max_fails=0; server 127.0.0.1:9031 max_fails=0; } server { listen 9039; location / { proxy_pass http://nginxretry; proxy_next_upstream error timeout http_500 non_idempotent; } }
重啟Nginx后再次使用POST請求訪問 http://localhost:9039/ ,再分別查看9030和9031兩個端口號對應的服務日志,可以看到兩個服務都收到請求,也就是POST請求也會重試了。不過實際上在生產(chǎn)環(huán)境中,不建議加上non_idempotent選項,具體原因可以繼續(xù)往下閱讀。
什么是冪等方法在HTTP協(xié)議規(guī)范中,對冪等方法(Idempotent Method)做了以下定義:
A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.
如果使用該方法的多個相同請求對服務器的預期效果與單個請求的效果相同,則認為請求方法是冪等的。常見的HTTP請求方法中,GET是冪等的,而POST是非冪等的。如果在回答面試題"GET和POST區(qū)別"時能答出這一點,才能說明對HTTP協(xié)議有一定的理解。
在做業(yè)務開發(fā)是如何理解冪等性,舉個最簡單的例子:GET方法一般用于獲取數(shù)據(jù),如果獲取的是數(shù)據(jù)庫數(shù)據(jù),對應的是SELECT語句。同樣的SELECT語句執(zhí)行一次還是多次,都不會影響數(shù)據(jù)。而POST一般對應INSERT,如果執(zhí)行多次后,可能會造成數(shù)據(jù)重復插入的問題。所以不要使用GET方法做一些INSERT操作,在業(yè)務開發(fā)時要遵循HTTP協(xié)議規(guī)范。
生產(chǎn)環(huán)境中為什么不建議加上non_idempotent選項?因為無論是發(fā)生500錯誤還是timeout,服務器上的業(yè)務可能都已經(jīng)執(zhí)行過了,而重試會導致非冪等方法重復執(zhí)行,從而導致業(yè)務問題,例如一個請求會創(chuàng)建了多個訂單,或者收到多條短信的問題。
參考文檔http://nginx.org/en/docs/http...
https://tools.ietf.org/html/r...
關注我文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40603.html
摘要:在這篇文章中,我們描述了我們如何在里設計重試,使能夠在最小化風險的同時,自動提高系統(tǒng)可靠性。配置重試的最常用方法,是指定在放棄之前執(zhí)行的最大重試次數(shù)。超時時,將取消請求并返回響應。但是在上面的服務配置文件中,我們將在服務器端指定重試政策。 showImg(https://segmentfault.com/img/bVbo113?w=4400&h=1007);作者:Alex Leong ...
摘要:重試會增加的響應時間。提供了輔助方法來為包含遠程調用的函數(shù)式接口或表達式創(chuàng)建裝飾器。如果我們想創(chuàng)建一個裝飾器并在代碼庫的不同位置重用它,我們將使用。 在本文中,我們將從快速介紹 Resilience4j 開始,然后深入探討其 Retry 模塊。我們將了解何時、如何使用它,以及它提供的功能。在此過程中,我們還將學...
摘要:如果要對冪等操作重試請求優(yōu)先參考上面的回答,下面是的示例參考網(wǎng)站關于該參數(shù)的詳細解釋學習總結與模塊三 轉載請注明出處 http://www.paraller.com 原文排版地址 點擊跳轉 轉載請注明出處 來源:parallers blog upstream www.paraller.com { server 10.29.209.14*:3810; ...
小編寫這篇文章的主要目的,主要是給大家講解一下,關于Python機制的一些問題,比如重新調試的機制是什么呢?應用到它的場景還是很多的,下面跟小編一塊去學習吧。 介紹: 為了避免網(wǎng)絡問題出現(xiàn)的錯誤,比如網(wǎng)絡延遲或者是宕機,往往都會出現(xiàn)請求超時的問題。 這里要給大家介紹的是一個第三方庫-Tenacity(標題中的重試機制并并不準確,它不是Python的內置模塊,因此并不能稱之為機制),它實現(xiàn)...
閱讀 2306·2023-04-25 14:17
閱讀 1514·2021-11-23 10:02
閱讀 2169·2021-11-23 09:51
閱讀 872·2021-10-14 09:49
閱讀 3383·2021-10-11 10:57
閱讀 2921·2021-09-24 09:47
閱讀 3045·2021-08-24 10:00
閱讀 2297·2019-08-29 18:46