成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Nginx失敗重試中的HTTP協(xié)議冪等問題: non_idempotent

edgardeng / 2132人閱讀

摘要:再次使用方式請(qǐng)求,再分別查看和兩個(gè)端口號(hào)對(duì)應(yīng)的服務(wù)日志,可以發(fā)現(xiàn)只有一個(gè)服務(wù)收到請(qǐng)求。常見的請(qǐng)求方法中,是冪等的,而是非冪等的。而一般對(duì)應(yīng),如果執(zhí)行多次后,可能會(huì)造成數(shù)據(jù)重復(fù)插入的問題。

Nginx通過反向代理做負(fù)載均衡時(shí),如果被代理的其中一個(gè)服務(wù)發(fā)生錯(cuò)誤或者超時(shí)的時(shí)候,通常希望Nginx自動(dòng)重試其他的服務(wù),從而實(shí)現(xiàn)服務(wù)的高可用性。實(shí)際上Nginx本身默認(rèn)會(huì)有錯(cuò)誤重試機(jī)制,并且可以通過proxy_next_upstream來自定義配置。

如果不了解HTTP協(xié)議以及Nginx的機(jī)制,就可能在使用過程中遇到各種各樣的坑。例如服務(wù)出現(xiàn)了錯(cuò)誤或超時(shí)卻未重試,或者一些例如創(chuàng)建訂單或發(fā)送短信這類的HTTP接口,客戶端只發(fā)送一次請(qǐng)求,后臺(tái)卻由于Nginx重試導(dǎo)致創(chuàng)建了多個(gè)訂單,或者收到多條短信,導(dǎo)致一些業(yè)務(wù)上的問題。

proxy_next_upstream

在Nginx配置文件中,proxy_next_upstream用于指定在什么情況下Nginx會(huì)將請(qǐng)求轉(zhuǎn)移到其他服務(wù)器上。其默認(rèn)值是proxy_next_upstream error timeout,即發(fā)生網(wǎng)絡(luò)錯(cuò)誤以及超時(shí),才會(huì)重試其他服務(wù)器。默認(rèn)情況下服務(wù)返回500狀態(tài)碼是不會(huì)重試的,如果想在響應(yīng)500狀態(tài)碼時(shí)也進(jìn)行重試,可以配置:

proxy_next_upstream error timeout http_500;

當(dāng)然還有http_502、http_503、http_404等可以指定在出現(xiàn)哪些狀態(tài)碼的情況下需要重試。具體配置項(xiàng)可以參考官方文檔: http://nginx.org/en/docs/http... 。

用一個(gè)最簡單的例子來測(cè)試一下該特性,例如下面是Spring Boot寫了一個(gè)簡單的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("收到一個(gè)請(qǐng)求"); // 打印日志
        throw new RuntimeException(); // 拋出異常, 返回500狀態(tài)碼
    }
}

分別使用9030和9031兩個(gè)端口號(hào)啟動(dòng)該Spring Boot服務(wù),然后Nginx配置好負(fù)載均衡:

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是為了更方便的測(cè)試Nginx錯(cuò)誤重試機(jī)制。max_fails默認(rèn)值是1,用于指定一個(gè)server在一段時(shí)間內(nèi)(默認(rèn)10s)發(fā)生錯(cuò)誤次數(shù)達(dá)到多少次,Nginx就會(huì)自動(dòng)將該服務(wù)器下線。這里設(shè)置為0是禁用這個(gè)特性,防止在測(cè)試過程中服務(wù)器被踢下線不好測(cè)試。線上環(huán)境下一般不會(huì)設(shè)置max_fails=0。

配置完成后重啟Nginx,使用GET方式請(qǐng)求 http://localhost:9039/ ,再分別查看9030和9031兩個(gè)端口號(hào)對(duì)應(yīng)的服務(wù)日志,可以發(fā)現(xiàn)兩個(gè)服務(wù)都收到請(qǐng)求,也就是Nginx在訪問其中一個(gè)服務(wù)收到500錯(cuò)誤狀態(tài)碼后,又嘗試去訪問另一個(gè)服務(wù)。

再次使用POST方式請(qǐng)求 http://localhost:9039/ ,再分別查看9030和9031兩個(gè)端口號(hào)對(duì)應(yīng)的服務(wù)日志,可以發(fā)現(xiàn)只有一個(gè)服務(wù)收到請(qǐng)求。也就是當(dāng)請(qǐng)求類型是POST時(shí),Nginx默認(rèn)不會(huì)失敗重試。如果想讓POST請(qǐng)求也會(huì)失敗重試,可以繼續(xù)向下閱讀。

non_idempotent

在Nginx文檔中可以看到proxy_next_upstream有一個(gè)選項(xiàng)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;

通常情況下,如果請(qǐng)求使用非等冪方法(POST、LOCK、PATCH),請(qǐng)求失敗后不會(huì)再到其他服務(wù)器進(jìn)行重試。加上non_idempotent選項(xiàng)后,即使是非冪等請(qǐng)求類型(例如POST請(qǐng)求),發(fā)生錯(cuò)誤后也會(huì)重試。

如果想讓POST請(qǐng)求也會(huì)失敗重試,需要配置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請(qǐng)求訪問 http://localhost:9039/ ,再分別查看9030和9031兩個(gè)端口號(hào)對(duì)應(yīng)的服務(wù)日志,可以看到兩個(gè)服務(wù)都收到請(qǐng)求,也就是POST請(qǐng)求也會(huì)重試了。不過實(shí)際上在生產(chǎn)環(huán)境中,不建議加上non_idempotent選項(xiàng),具體原因可以繼續(xù)往下閱讀。

什么是冪等方法

在HTTP協(xié)議規(guī)范中,對(duì)冪等方法(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.

如果使用該方法的多個(gè)相同請(qǐng)求對(duì)服務(wù)器的預(yù)期效果與單個(gè)請(qǐng)求的效果相同,則認(rèn)為請(qǐng)求方法是冪等的。常見的HTTP請(qǐng)求方法中,GET是冪等的,而POST是非冪等的。如果在回答面試題"GET和POST區(qū)別"時(shí)能答出這一點(diǎn),才能說明對(duì)HTTP協(xié)議有一定的理解。

在做業(yè)務(wù)開發(fā)是如何理解冪等性,舉個(gè)最簡單的例子:GET方法一般用于獲取數(shù)據(jù),如果獲取的是數(shù)據(jù)庫數(shù)據(jù),對(duì)應(yīng)的是SELECT語句。同樣的SELECT語句執(zhí)行一次還是多次,都不會(huì)影響數(shù)據(jù)。而POST一般對(duì)應(yīng)INSERT,如果執(zhí)行多次后,可能會(huì)造成數(shù)據(jù)重復(fù)插入的問題。所以不要使用GET方法做一些INSERT操作,在業(yè)務(wù)開發(fā)時(shí)要遵循HTTP協(xié)議規(guī)范。

生產(chǎn)環(huán)境中為什么不建議加上non_idempotent選項(xiàng)?因?yàn)闊o論是發(fā)生500錯(cuò)誤還是timeout,服務(wù)器上的業(yè)務(wù)可能都已經(jīng)執(zhí)行過了,而重試會(huì)導(dǎo)致非冪等方法重復(fù)執(zhí)行,從而導(dǎo)致業(yè)務(wù)問題,例如一個(gè)請(qǐng)求會(huì)創(chuàng)建了多個(gè)訂單,或者收到多條短信的問題。

參考文檔

http://nginx.org/en/docs/http...

https://tools.ietf.org/html/r...

關(guān)注我

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/40603.html

相關(guān)文章

  • 我們?nèi)绾卧贚inkerd 2.2里設(shè)計(jì)重試

    摘要:在這篇文章中,我們描述了我們?nèi)绾卧诶镌O(shè)計(jì)重試,使能夠在最小化風(fēng)險(xiǎn)的同時(shí),自動(dòng)提高系統(tǒng)可靠性。配置重試的最常用方法,是指定在放棄之前執(zhí)行的最大重試次數(shù)。超時(shí)時(shí),將取消請(qǐng)求并返回響應(yīng)。但是在上面的服務(wù)配置文件中,我們將在服務(wù)器端指定重試政策。 showImg(https://segmentfault.com/img/bVbo113?w=4400&h=1007);作者:Alex Leong ...

    Mike617 評(píng)論0 收藏0
  • 使用 Resilience4j 框架實(shí)現(xiàn)重試機(jī)制

    摘要:重試會(huì)增加的響應(yīng)時(shí)間。提供了輔助方法來為包含遠(yuǎn)程調(diào)用的函數(shù)式接口或表達(dá)式創(chuàng)建裝飾器。如果我們想創(chuàng)建一個(gè)裝飾器并在代碼庫的不同位置重用它,我們將使用。 在本文中,我們將從快速介紹 Resilience4j 開始,然后深入探討其 Retry 模塊。我們將了解何時(shí)、如何使用它,以及它提供的功能。在此過程中,我們還將學(xué)...

    番茄西紅柿 評(píng)論0 收藏2637
  • 超時(shí)重試思考-非冪等請(qǐng)求

    摘要:如果要對(duì)冪等操作重試請(qǐng)求優(yōu)先參考上面的回答,下面是的示例參考網(wǎng)站關(guān)于該參數(shù)的詳細(xì)解釋學(xué)習(xí)總結(jié)與模塊三 轉(zhuǎn)載請(qǐng)注明出處 http://www.paraller.com 原文排版地址 點(diǎn)擊跳轉(zhuǎn) 轉(zhuǎn)載請(qǐng)注明出處 來源:parallers blog upstream www.paraller.com { server 10.29.209.14*:3810; ...

    Miracle 評(píng)論0 收藏0
  • Python重試機(jī)制是什么,下文給大家解答

      小編寫這篇文章的主要目的,主要是給大家講解一下,關(guān)于Python機(jī)制的一些問題,比如重新調(diào)試的機(jī)制是什么呢?應(yīng)用到它的場景還是很多的,下面跟小編一塊去學(xué)習(xí)吧?! 〗榻B:  為了避免網(wǎng)絡(luò)問題出現(xiàn)的錯(cuò)誤,比如網(wǎng)絡(luò)延遲或者是宕機(jī),往往都會(huì)出現(xiàn)請(qǐng)求超時(shí)的問題?! ∵@里要給大家介紹的是一個(gè)第三方庫-Tenacity(標(biāo)題中的重試機(jī)制并并不準(zhǔn)確,它不是Python的內(nèi)置模塊,因此并不能稱之為機(jī)制),它實(shí)現(xiàn)...

    89542767 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<