Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single. 《rfc2616 - 9.1.2 Idempotent Methods》html
以上是摘自HTTP1.1標準中有關冪等性的介紹,大體內容爲,除開網絡錯誤以及請求超時的問題,請求同一個接口屢次和單次,對資源所形成的影響是一致的。前端
這裏須要注意的是,冪等性關注的是對資源形成的影響,而非請求返回的結果。nginx
例如咱們設計了一個GET
接口api/getSystemTime
,用於返回服務器的實時時間,雖然每次返回的結果都是不同的,可是對服務器來講並無發生資源變更,因此也是冪等的。算法
通常來講,GET
、OPTIONS
、HEAD
、DELETE
這些請求方法都是冪等的,由於對服務器資源都是沒有影響的,或是產生的影響是一致的。像POST
、PUT
、PATCH
這些請求方法通常都是非冪等的。api
固然,有一些業務場景下,咱們須要用到POST
接口,同時也要保證冪等性,咱們也能夠本身實現接口的冪等性。緩存
通常咱們定義冪等性接口的使用場景是防止出現請求屢次而致使的服務結果不一致的狀況。例如付款接口,用戶在前端可能由於點擊屢次,發起了屢次請求,若是這個時候接口不作好冪等性的話,可能會出現屢次付款的狀況。服務器
實現冪等性能夠從控制資源訪問的次數下手。網絡
即便有多個請求過來須要請求支付,咱們只須要容許其中一次請求進行完整的支付流程,其餘請求均放棄便可。ide
這樣咱們能夠延伸出token
的概念。測試
假設咱們的系統由訂單系統和支付系統兩部分組成,當咱們提交訂單後,由訂單系統向支付系統申請一個token,支付系統在生成後返回這個token,同時將token存至Redis緩存中。這樣當咱們向支付系統發起支付請求時,帶上這個token,支付系統須要先判斷一下在緩存中是否存在這個token,若是存在則刪除這個token,同時繼續執行支付邏輯;若是緩存中不存在這個token,則返回業務錯誤。
這裏的token相似於一個信物,只有持有這個信物的人才容許被放行,放行後,這個信物也不被信任,下次即便有攜帶相同信物來的人,也不給放行。
寫到最後,忽然想起來爲啥要研究這個冪等性
來着。
當時是在一個客戶現場出現的生產問題,咱們的應用程序,經過nginx
往算法服務發送一個POST請求後,在通過大概10分鐘,算法忽然又被調用了一次,且收到的參數和第一次一摸同樣。一開始覺得是應用程序的問題,在公司的測試環境模擬了一遍,沒有復現,後來懷疑多是nginx
作的鬼,問了現場,才知道現場使用的nginx
版本是1.8.1
(吐槽一下版本有點老)。而後在網上查閱資料,得知1.9.13之前版本的nginx默認會將POST等非冪等請求作超時重試處理。雖然咱們的應用程序在往算法發起請求後,就不會再作什麼後續處理,但坑的是算法會保持這個請求也不返回數據,致使nginx
認爲請求超時了,又發起了一波請求,血與淚哦。
因爲不能讓現場升級nginx,因此咱們只能讓現場在nginx
中加大了那個算法接口的超時時間。
下面摘自nginx
官方文檔。
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;