何為冪等可重試(安全操作)
阿新 • • 發佈:2019-02-18
google了一些中文的資料, 基本瞭解了冪等是怎麼回事兒. 備忘一下.
PUT,DELETE操作是冪等的。所謂冪等是指不管進行多少次操作,結果都一樣。比如我用PUT修改一篇文章,然後在做同樣的操作,每次操作後的結果並沒有不同,DELETE也是一樣。順便說一句,因為GET操作是安全的,所以它自然也是冪等的。
POST操作既不是安全的,也不是冪等的,比如常見的POST重複載入問題:當我們多次發出同樣的POST請求後,其結果是創建出了若干的資源。
安全和冪等的意義在於:當操作沒有達到預期的目標時,我們可以不停的重試,而不會對資源產生副作用。從這個意義上說,POST操作往往是有害的,但很多時候我們還是不得不使用它。
還有一點需要注意的就是,建立操作可以使用POST,也可以使用PUT,區別在於POST是作用在一個集合資源之上的(/articles),而PUT操作是作用在一個具體資源之上的(/articles/123),再通俗點說,如果URL可以在客戶端確定,那麼就使用PUT,如果是在服務端確定,那麼就使用POST,比如說很多資源使用資料庫自增主鍵作為標識資訊,而建立的資源的標識資訊到底是什麼只能由服務端提供,這個時候就必須使用POST。
一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等操作對於代理和快取來說具有“友好性”,因為冪等操作的額外執行不會對二者產生危害性後果(除了頻寬浪費)。
PUT方法是冪等的,冪等性意味著對於一個成功執行的請求,不管其執行多少次,其結果都是一致的。也就是說,只要你願意,你可以用PUT方法對 Hotel資源進行任意次更新,其結果都一樣。如果兩個PUT方法同時發生,那麼只有其中之一會贏得最後的勝利並決定資源的最終狀態。刪除操作也是冪等的,如果一個PUT方法和DELETE方法同時發生,那麼資源或者被更新,或者被刪除,而不可能停留在某個中間狀態。
如果你不確定是PUT還是DELETE被成功執行,並且沒有得到狀態碼409 (Conflict)或者 417 (Expectation Failed)的話,那麼就重新執行一遍。而不需要附加的可靠性協議來避免重複請求,因為通常重複的請求不會有任何影響。
上述描述對於POST方法就不適用了,因為POST方法不是冪等的,若要兩次執行同一個POST請求那就要注意了。POST方法所缺失的冪等性就解釋了為什麼當你每次重新發送POST請求時瀏覽器總是彈出警告。POST方法用於建立資源,而不需要由客戶端指定例項id
冪等函式,或冪等方法,是指可以使用相同引數重複執行,並能獲得相同結果的函式。這些函式不會影響系統狀態,也不用擔心重複執行會對系統造成改變。例如,“getUsername()”函式就是一個冪等函式,“deleteFile()”函式就不是。“冪等”是HTTP Session和EJB失敗轉移中的一個重要概念。
當正在進行方法呼叫的時候失敗了怎麼辦呢?答案是:處理過程中止,客戶端看見錯誤訊息提示(除非方法是冪等方法)。只有方法是冪等方法的情況,一些負載均衡器才能試圖失敗轉移這些方法到別的例項。
冪等為何如此重要?因為客戶端並不知道伺服器何時失敗的(在方法剛開始呼叫或者快要呼叫完成的時候)。如果是非冪等方法,則兩次呼叫就會兩次改變系統狀態,系統就會處於不一致的狀態。
在複雜應用中,不太可能把所有的方法都變成冪等方法。所以,只能通過失敗轉移減少錯誤,而不可能從根本上避免錯誤。
把應用程式設計為冪等的:冪等的的意思就是一個操做不會修改狀態資訊,並且每次操作的時候都返回同樣的結果(換句話說就是:做多次和做一次的效果是一樣的),通常,WEB請求,特別是 HTML forms 都被髮送多次(當用戶點擊發送按紐兩次,過載頁面多次),導致多次HTTP請求。設計SERVLET和其他WEB物件為 冪等的,可以容忍多次請求。詳細可以去參考設計模式“Synchronized Token ”和“Idempotent Receiver ”關於怎樣設計冪等的的應用程式。
PUT,DELETE操作是冪等的。所謂冪等是指不管進行多少次操作,結果都一樣。比如我用PUT修改一篇文章,然後在做同樣的操作,每次操作後的結果並沒有不同,DELETE也是一樣。順便說一句,因為GET操作是安全的,所以它自然也是冪等的。
POST操作既不是安全的,也不是冪等的,比如常見的POST重複載入問題:當我們多次發出同樣的POST請求後,其結果是創建出了若干的資源。
安全和冪等的意義在於:當操作沒有達到預期的目標時,我們可以不停的重試,而不會對資源產生副作用。從這個意義上說,POST操作往往是有害的,但很多時候我們還是不得不使用它。
還有一點需要注意的就是,建立操作可以使用POST,也可以使用PUT,區別在於POST是作用在一個集合資源之上的(/articles),而PUT操作是作用在一個具體資源之上的(/articles/123),再通俗點說,如果URL可以在客戶端確定,那麼就使用PUT,如果是在服務端確定,那麼就使用POST,比如說很多資源使用資料庫自增主鍵作為標識資訊,而建立的資源的標識資訊到底是什麼只能由服務端提供,這個時候就必須使用POST。
一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等操作對於代理和快取來說具有“友好性”,因為冪等操作的額外執行不會對二者產生危害性後果(除了頻寬浪費)。
PUT方法是冪等的,冪等性意味著對於一個成功執行的請求,不管其執行多少次,其結果都是一致的。也就是說,只要你願意,你可以用PUT方法對 Hotel資源進行任意次更新,其結果都一樣。如果兩個PUT方法同時發生,那麼只有其中之一會贏得最後的勝利並決定資源的最終狀態。刪除操作也是冪等的,如果一個PUT方法和DELETE方法同時發生,那麼資源或者被更新,或者被刪除,而不可能停留在某個中間狀態。
如果你不確定是PUT還是DELETE被成功執行,並且沒有得到狀態碼409 (Conflict)或者 417 (Expectation Failed)的話,那麼就重新執行一遍。而不需要附加的可靠性協議來避免重複請求,因為通常重複的請求不會有任何影響。
上述描述對於POST方法就不適用了,因為POST方法不是冪等的,若要兩次執行同一個POST請求那就要注意了。POST方法所缺失的冪等性就解釋了為什麼當你每次重新發送POST請求時瀏覽器總是彈出警告。POST方法用於建立資源,而不需要由客戶端指定例項id
冪等函式,或冪等方法,是指可以使用相同引數重複執行,並能獲得相同結果的函式。這些函式不會影響系統狀態,也不用擔心重複執行會對系統造成改變。例如,“getUsername()”函式就是一個冪等函式,“deleteFile()”函式就不是。“冪等”是HTTP Session和EJB失敗轉移中的一個重要概念。
當正在進行方法呼叫的時候失敗了怎麼辦呢?答案是:處理過程中止,客戶端看見錯誤訊息提示(除非方法是冪等方法)。只有方法是冪等方法的情況,一些負載均衡器才能試圖失敗轉移這些方法到別的例項。
冪等為何如此重要?因為客戶端並不知道伺服器何時失敗的(在方法剛開始呼叫或者快要呼叫完成的時候)。如果是非冪等方法,則兩次呼叫就會兩次改變系統狀態,系統就會處於不一致的狀態。
在複雜應用中,不太可能把所有的方法都變成冪等方法。所以,只能通過失敗轉移減少錯誤,而不可能從根本上避免錯誤。
把應用程式設計為冪等的:冪等的的意思就是一個操做不會修改狀態資訊,並且每次操作的時候都返回同樣的結果(換句話說就是:做多次和做一次的效果是一樣的),通常,WEB請求,特別是 HTML forms 都被髮送多次(當用戶點擊發送按紐兩次,過載頁面多次),導致多次HTTP請求。設計SERVLET和其他WEB物件為 冪等的,可以容忍多次請求。詳細可以去參考設計模式“Synchronized Token ”和“Idempotent Receiver ”關於怎樣設計冪等的的應用程式。