一趟紊、前言
- 基于HTTP協(xié)議的Web API是時下最為流行的一種分布式服務提供方式。
- 互聯(lián)網(wǎng)應用架構設計表現(xiàn)出了從傳統(tǒng)的PHP碰酝、JSP霎匈、ASP.NET等服務器端動態(tài)網(wǎng)頁向Restful API + JSON過渡的趨勢,前后端分離越來越普遍送爸。
二铛嘱、冪等性定義
本文所要探討的正是HTTP協(xié)議涉及到的一種重要性質(zhì):冪等性(Idempotence)。在HTTP/1.1規(guī)范中冪等性的定義是:
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 request.
從定義上看袭厂,HTTP方法的冪等性是指一次和多次請求某一個資源應該具有同樣的副作用墨吓。冪等性屬于語義范疇,正如編譯器只能幫助檢查語法錯誤一樣纹磺,HTTP規(guī)范也沒有辦法通過消息格式等語法手段來定義它帖烘,這可能是它不太受到重視的原因之一。但實際上橄杨,冪等性是分布式系統(tǒng)設計中十分重要的概念秘症,而HTTP的分布式本質(zhì)也決定了它在HTTP中具有重要地位。
三讥珍、GET历极、DELETE、PUT衷佃、POST語義和冪等性趟卸。
HTTP GET方法用于獲取資源,不應有副作用,所以是冪等的锄列。比如:GET http://www.bank.com/account/123456图云,不會改變資源的狀態(tài),不論調(diào)用一次還是N次都沒有副作用邻邮。請注意竣况,這里強調(diào)的是一次和N次具有相同的副作用,而不是每次GET的結果相同筒严。GET http://www.news.com/latest-news這個HTTP請求可能會每次得到不同的結果丹泉,但它本身并沒有產(chǎn)生任何副作用,因而是滿足冪等性的鸭蛙。
HTTP DELETE方法用于刪除資源摹恨,有副作用,但它應該滿足冪等性娶视。比如:DELETE http://www.forum.com/article/4231晒哄,調(diào)用一次和N次對系統(tǒng)產(chǎn)生的副作用是相同的,即刪掉id為4231的帖子肪获;因此寝凌,調(diào)用者可以多次調(diào)用或刷新頁面而不必擔心引起錯誤。
比較容易混淆的是HTTP POST和PUT孝赫。POST和PUT的區(qū)別容易被簡單地誤認為“POST表示創(chuàng)建資源较木,PUT表示更新資源”;而實際上寒锚,二者均可用于創(chuàng)建資源劫映,更為本質(zhì)的差別是在冪等性方面。在HTTP規(guī)范中對POST和PUT是這樣定義的:
The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.
- POST所對應的URI并非創(chuàng)建的資源本身刹前,而是資源的接收者泳赋。比如:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下創(chuàng)建一篇帖子,HTTP響應中應包含帖子的創(chuàng)建狀態(tài)以及帖子的URI喇喉。兩次相同的POST請求會在服務器端創(chuàng)建兩份資源祖今,它們具有不同的URI;所以拣技,POST方法不具備冪等性千诬。而PUT所對應的URI是要創(chuàng)建或更新的資源本身。比如:PUT http://www.forum/articles/4231的語義是創(chuàng)建或更新ID為4231的帖子膏斤。對同一URI進行多次PUT的副作用和一次PUT是相同的徐绑;因此,PUT方法具有冪等性莫辨。
四傲茄、總結
- 一個冪等的操作典型如:
把編號為5的記錄的A字段設置為0這種操作不管執(zhí)行多少次都是冪等的毅访。
一個非冪等的操作典型如:把編號為5的記錄的A字段增加1這種操作顯然就不是冪等的。
要做到冪等性盘榨,從接口設計上來說不設計任何非冪等的操作即可喻粹。
譬如說需求是:
當用戶點擊贊同時,將答案的贊同數(shù)量+1草巡。
改為:當用戶點擊贊同時守呜,確保答案贊同表中存在一條記錄(插入之前檢查這條記錄是否已經(jīng)存在,這在非冪等性的POST請求中山憨,表現(xiàn)的尤為重要)查乒,用戶、答案郁竟。贊同數(shù)量由答案贊同表統(tǒng)計出來侣颂。
分布式高并發(fā)并不意味著每個request都處理的很快,也不意味著機器之間就不共享數(shù)據(jù)了枪孩。其次,你可以把你所有帶有副作用的task都給一個guid藻肄,最后寫進數(shù)據(jù)庫之前查一下這個guid是否已經(jīng)被執(zhí)行過了蔑舞。
冪等性是數(shù)學中的一個概念,表達的是N次變換與1次變換的結果相同嘹屯。