1. 程式人生 > >理解http的冪等性

理解http的冪等性

比較 第一次 接收 出現問題 做到 的區別 重復提交 都沒有 在操作

冪等性是什麽?

冪等性——是系統的接口對外一種承諾(而不是實現),承諾只要調用接口成功,外部多次調用對系統的影響是一致的。
一個冪等的操作典型如:把編號為5的記錄的A字段設置為0,這種操作不管執行多少次都是冪等的。
一個非冪等的操作典型如:把編號為5的記錄的A字段增加1,這種操作顯然就不是冪等的。

要做到冪等性,從接口設計上來說不設計任何非冪等的操作即可。譬如說需求是:
當用戶點擊贊同時,將答案的贊同數量+1。改為:
當用戶點擊贊同時,確保答案贊同表中存在一條記錄,用戶、答案。贊同數量由答案贊同表統計出來。

HTTP冪等性是什麽?

HTTP協議本身是一種面向資源的應用層協議,但對HTTP協議的使用實際上存在著兩種不同的方式:一種是RESTful的,它把HTTP當成應用層協議,比較忠實地遵守了HTTP協議的各種規定;另一種是SOA的,它並沒有完全把HTTP當成應用層協議,而是把HTTP協議作為了傳輸層協議,然後在HTTP之上建立了自己的應用層協議。本文所討論的HTTP冪等性主要針對RESTful風格的,不過正如上一節所看到的那樣,冪等性並不屬於特定的協議,它是分布式系統的一種特性;所以,不論是SOA還是RESTful的Web API設計都應該考慮冪等性。下面將介紹HTTP GET、DELETE、PUT、POST四種主要方法的語義和冪等性。
1)GET

HTTPGET方法用於獲取資源,不應有副作用,所以是冪等的。比如:GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次還是N次都沒有副作用。請註意,這裏強調的是一次和N次具有相同的副作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次得到不同的結果,但它本身並沒有產生任何副作用,因而是滿足冪等性的。

2)DELETE

HTTPDELETE方法用於刪除資源,有副作用,但它應該滿足冪等性。比如:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的副作用是相同的,即刪掉id為4231的帖子;因此,調用者可以多次調用或刷新頁面而不必擔心引起錯誤。

3)POST

比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認為“POST表示創建資源,PUT表示更新資源”;而實際上,二者均可用於創建資源,更為本質的差別是在冪等性方面。POST所對應的URI並非創建的資源本身,而是資源的接收者。比如:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下創建一篇帖子,HTTP響應中應包含帖子的創建狀態以及帖子的URI。兩次相同的POST請求會在服務器端創建兩份資源,它們具有不同的URI;所以,POST方法不具備冪等性。

4)PUT

而PUT所對應的URI是要創建或更新的資源本身。比如:PUT http://www.forum/articles/4231的語義是創建或更新ID為4231的帖子。第一次PUT方法執行之後,其在服務器上生成的資源,不能被後續的PUT方法更改,所以對同一URI進行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有冪等性。

電商應用中如何防範 POST 重復提交?

HTTP POST 操作既不是安全的,也不是冪等的(至少在HTTP規範裏沒有保證)。當我們因為反復刷新瀏覽器導致多次提交表單,多次發出同樣的POST請求,導致遠端服務器重復創建出了資源。
所以,對於電商應用來說,第一對應的後端 WebService 一定要做到冪等性,第二服務器端收到 POST 請求,在操作成功後必須302跳轉到另外一個頁面,這樣即使用戶刷新頁面,也不會重復提交表單。

具備“冪等性”的方法是安全的,因此在程序中冪等性也是應該追求的一項性質,很多時候程序不應該假定用戶的行為,不能因為用戶的重復操作而導致數據出現問題。

理解http的冪等性