- 1.post珊拼、put、patch:與冪等性
總:
用于上傳數(shù)據(jù)的方法只有POST友雳、PUT稿湿、PATCH。
PUT方法和PATCH方法所請(qǐng)求的目標(biāo)地址都是直接指向資源的押赊,而POST方法請(qǐng)求的目標(biāo)是一個(gè)行為處理器缎罢。PUT用于替換資源,而PATCH用于更新部分資源考杉。
分:
POST所對(duì)應(yīng)的URI并非創(chuàng)建的資源本身策精,而是資源的接收者。比如:POST http://www.forum.com/articles 的語義是在http://www.forum.com/articles 下創(chuàng)建一篇帖子崇棠,HTTP響應(yīng)中應(yīng)包含帖子的創(chuàng)建狀態(tài)以及帖子的URI咽袜。兩次相同的POST請(qǐng)求會(huì)在服務(wù)器端創(chuàng)建兩份資源,它們具有不同的URI枕稀;所以询刹,POST方法不具備冪等性谜嫉。
而PUT所對(duì)應(yīng)的URI是要?jiǎng)?chuàng)建或更新的資源本身。比如:PUT http://www.forum/articles/4231 的語義是創(chuàng)建或更新ID為4231的帖子凹联。對(duì)同一URI進(jìn)行多次PUT的副作用和一次PUT是相同的沐兰;因此,PUT方法有冪等性蔽挠。
POST方法非冪等可以理解住闯,因?yàn)樗?qǐng)求服務(wù)器執(zhí)行一個(gè)動(dòng)作,多次發(fā)起請(qǐng)求可能導(dǎo)致動(dòng)作多次執(zhí)行澳淑。
而像PATCH這樣請(qǐng)求的目標(biāo)是一個(gè)資源的比原,PATCH方法和POST方法有個(gè)很相似的地方,它們的實(shí)體部分都是結(jié)構(gòu)化的數(shù)據(jù)杠巡。POST方法的實(shí)體結(jié)構(gòu)一般是 multipart/form-data 或 application/x-www-form-urlencoded 而PATCH方法的實(shí)體結(jié)構(gòu)則隨其它規(guī)范定義量窘。
這和PUT方法的無結(jié)構(gòu)實(shí)體相比就是最大的區(qū)別∏庥担 PUT方法的實(shí)體無結(jié)構(gòu)的蚌铜,它直接把實(shí)體部分的數(shù)據(jù)替換到服務(wù)器的資源上。f而PATCH提供的實(shí)體則需要根據(jù)程序或其它協(xié)議的定義嫩海,解析后在服務(wù)器上執(zhí)行厘线,以此來修改服務(wù)器上的數(shù)據(jù)。也就是說出革,PATCH請(qǐng)求是會(huì)執(zhí)行某個(gè)程序的造壮,如果重復(fù)提交,程序可能執(zhí)行多次骂束,對(duì)服務(wù)器上的資源就可能造成額外的影響耳璧,這就可以解釋它為什么是不冪等的了。
- 2.為什么需要冪等性呢展箱?我們先從一個(gè)例子說起旨枯,假設(shè)有一個(gè)從賬戶取錢的遠(yuǎn)程API(可以是HTTP的,也可以不是)混驰,我們暫時(shí)用類函數(shù)的方式記為:
bool withdraw(account_id, amount)
withdraw的語義是從account_id對(duì)應(yīng)的賬戶中扣除amount數(shù)額的錢攀隔;如果扣除成功則返回true,賬戶余額減少amount栖榨;如果扣除失敗則返回false昆汹,賬戶余額不變。值得注意的是:和本地環(huán)境相比婴栽,我們不能輕易假設(shè)分布式環(huán)境的可靠性满粗。一種典型的情況是withdraw請(qǐng)求已經(jīng)被服務(wù)器端正確處理,但服務(wù)器端的返回結(jié)果由于網(wǎng)絡(luò)等原因被掉丟了愚争,導(dǎo)致客戶端無法得知處理結(jié)果映皆。如果是在網(wǎng)頁上挤聘,一些不恰當(dāng)?shù)脑O(shè)計(jì)可能會(huì)使用戶認(rèn)為上一次操作失敗了,然后刷新頁面捅彻,這就導(dǎo)致了withdraw被調(diào)用兩次组去,賬戶也被多扣了一次錢。
另一種更輕量級(jí)的解決方案是冪等設(shè)計(jì)步淹。我們可以通過一些技巧把withdraw變成冪等的从隆,比如:
int create_ticket() bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的語義是獲取一個(gè)服務(wù)器端生成的唯一的處理號(hào)ticket_id,它將用于標(biāo)識(shí)后續(xù)的操作贤旷。idempotent_withdraw和withdraw的區(qū)別在于關(guān)聯(lián)了一個(gè)ticket_id广料,一個(gè)ticket_id表示的操作至多只會(huì)被處理一次砾脑,每次調(diào)用都將返回第一次調(diào)用時(shí)的處理結(jié)果幼驶。這樣,idempotent_withdraw就符合冪等性了韧衣,客戶端就可以放心地多次調(diào)用盅藻。
基于冪等性的解決方案中一個(gè)完整的取錢流程被分解成了兩個(gè)步驟:1.調(diào)用create_ticket()獲取ticket_id;2.調(diào)用idempotent_withdraw(ticket_id, account_id, amount)畅铭。雖然create_ticket不是冪等的氏淑,但在這種設(shè)計(jì)下,它對(duì)系統(tǒng)狀態(tài)的影響可以忽略硕噩,加上idempotent_withdraw是冪等的假残,所以任何一步由于網(wǎng)絡(luò)等原因失敗或超時(shí),客戶端都可以重試炉擅,直到獲得結(jié)果辉懒。如圖2所示:
- 3.說一下get 、delete:
HTTP GET方法用于獲取資源谍失,不應(yīng)有副作用眶俩,所以是冪等的。比如:GET http://www.bank.com/account/123456 快鱼,不會(huì)改變資源的狀態(tài)颠印,不論調(diào)用一次還是N次都沒有副作用。請(qǐng)注意抹竹,這里強(qiáng)調(diào)的是一次和N次具有相同的副作用线罕,而不是每次GET的結(jié)果相同。GET http://www.news.com/latest-news 這個(gè)HTTP請(qǐng)求可能會(huì)每次得到不同的結(jié)果窃判,但它本身并沒有產(chǎn)生任何副作用闻坚,因而是滿足冪等性的。
HTTP DELETE方法用于刪除資源兢孝,有副作用窿凤,但它應(yīng)該滿足冪等性仅偎。比如:DELETE http://www.forum.com/article/4231 ,調(diào)用一次和N次對(duì)系統(tǒng)產(chǎn)生的副作用是相同的雳殊,即刪掉id為4231的帖子橘沥;因此,調(diào)用者可以多次調(diào)用或刷新頁面而不必?fù)?dān)心引起錯(cuò)誤夯秃。
- 4.說一下post 和 get的區(qū)別座咆?