国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

人人都是 API 設(shè)計(jì)師:我對 RESTful API、GraphQL、RPC API 的思考

FWHeart / 2038人閱讀

摘要:通常情況下,偽都是基于第一層次與第二層次設(shè)計(jì)的。為了解決這個(gè)版本不兼容問題,在設(shè)計(jì)的一種實(shí)用的做法是使用版本號。例如,建議第三位版本號通常表示兼容升級,只有不兼容時(shí)才需要變更服務(wù)版本。

原文地址:梁桂釗的博客

博客地址:http://blog.720ui.com

歡迎關(guān)注公眾號:「服務(wù)端思維」。一群同頻者,一起成長,一起精進(jìn),打破認(rèn)知的局限性。

有一段時(shí)間沒怎么寫文章了,今天提筆寫一篇自己對 API 設(shè)計(jì)的思考。首先,為什么寫這個(gè)話題呢?其一,我閱讀了《阿里研究員谷樸:API 設(shè)計(jì)最佳實(shí)踐的思考》一文后受益良多,前兩天并轉(zhuǎn)載了這篇文章也引發(fā)了廣大讀者的興趣,我覺得我應(yīng)該把我自己的思考整理成文與大家一起分享與碰撞。其二,我覺得我針對這個(gè)話題,可以半個(gè)小時(shí)之內(nèi)搞定,爭取在 1 點(diǎn)前關(guān)燈睡覺,哈哈。

現(xiàn)在,我們來一起探討 API 的設(shè)計(jì)之道。我會拋出幾個(gè)觀點(diǎn),歡迎探討。

一、定義好的規(guī)范,已經(jīng)成功了一大半

通常情況下,規(guī)范就是大家約定俗成的標(biāo)準(zhǔn),如果大家都遵守這套標(biāo)準(zhǔn),那么自然溝通成本大大降低。例如,大家都希望從阿里的規(guī)范上面學(xué)習(xí),在自己的業(yè)務(wù)中也定義幾個(gè)領(lǐng)域模型:VO、BO、DO、DTO。其中,DO(Data Object)與數(shù)據(jù)庫表結(jié)構(gòu)一一對應(yīng),通過 DAO 層向上傳輸數(shù)據(jù)源對象。 而 DTO(Data Transfer Object)是遠(yuǎn)程調(diào)用對象,它是 RPC 服務(wù)提供的領(lǐng)域模型。對于 BO(Business Object),它是業(yè)務(wù)邏輯層封裝業(yè)務(wù)邏輯的對象,一般情況下,它是聚合了多個(gè)數(shù)據(jù)源的復(fù)合對象。那么,VO(View Object) 通常是請求處理層傳輸?shù)膶ο螅ㄟ^ Spring 框架的轉(zhuǎn)換后,往往是一個(gè) JSON 對象。

事實(shí)上,阿里這種復(fù)雜的業(yè)務(wù)中如果不劃分清楚 ?DO、BO、DTO、VO 的領(lǐng)域模型,其內(nèi)部代碼很容易就混亂了,內(nèi)部的 RPC 在 service 層的基礎(chǔ)上又增加了 manager 層,從而實(shí)現(xiàn)內(nèi)部的規(guī)范統(tǒng)一化。但是,如果只是多帶帶的域又沒有太多外部依賴,那么,完全不要設(shè)計(jì)這么復(fù)雜,除非預(yù)期到可能會變得龐大和復(fù)雜化。對此,設(shè)計(jì)過程中因地制宜就顯得特別重要了。

另外一個(gè)規(guī)范的例子是 RESTful API。在 REST 架構(gòu)風(fēng)格中,每一個(gè) URI 代表一種資源。因此,URI 是每一個(gè)資源的地址的唯一資源定位符。所謂資源,實(shí)際上就是一個(gè)信息實(shí)體,它可以是服務(wù)器上的一段文本、一個(gè)文件、一張圖片、一首歌曲,或者是一種服務(wù)。RESTful API 規(guī)定了通過 GET、 POST、 PUT、 PATCH、 DELETE 等方式對服務(wù)端的資源進(jìn)行操作。

【GET】          /users                 # 查詢用戶信息列表
【GET】          /users/1001            # 查看某個(gè)用戶信息
【POST】         /users                 # 新建用戶信息
【PUT】          /users/1001            # 更新用戶信息(全部字段)
【PATCH】        /users/1001            # 更新用戶信息(部分字段)
【DELETE】       /users/1001            # 刪除用戶信息

事實(shí)上,RESTful API 的實(shí)現(xiàn)分了四個(gè)層級。第一層次(Level 0)的 Web API 服務(wù)只是使用 HTTP 作為傳輸方式。第二層次(Level 1)的 Web API 服務(wù)引入了資源的概念。每個(gè)資源有對應(yīng)的標(biāo)識符和表達(dá)。第三層次(Level 2)的 Web API 服務(wù)使用不同的 HTTP 方法來進(jìn)行不同的操作,并且使用 HTTP 狀態(tài)碼來表示不同的結(jié)果。第四層次(Level 3)的 Web API 服務(wù)使用 HATEOAS。在資源的表達(dá)中包含了鏈接信息。客戶端可以根據(jù)鏈接來發(fā)現(xiàn)可以執(zhí)行的動作。通常情況下,偽 RESTful API 都是基于第一層次與第二層次設(shè)計(jì)的。例如,我們的 Web API 中使用各種動詞,例如 get_menu?和 save_menu?,而真正意義上的?RESTful API 需要滿足第三層級以上。如果我們遵守了這套規(guī)范,我們就很可能就設(shè)計(jì)出通俗易懂的 API。

注意的是,定義好的規(guī)范,我們已經(jīng)成功了一大半。如果這套規(guī)范是業(yè)內(nèi)標(biāo)準(zhǔn),那么我們可以大膽實(shí)踐,不要擔(dān)心別人不會用,只要把業(yè)界標(biāo)準(zhǔn)丟給他好好學(xué)習(xí)一下就可以啦。例如,Spring 已經(jīng)在 Java 的生態(tài)中舉足輕重,如果一個(gè)新人不懂 Spring 就有點(diǎn)說不過去了。但是,很多時(shí)候因?yàn)闃I(yè)務(wù)的限制和公司的技術(shù),我們可能使用基于第一層次與第二層次設(shè)計(jì)的偽 RESTful API,但是它不一定就是落后的,不好的,只要團(tuán)隊(duì)內(nèi)部形成規(guī)范,降低大家的學(xué)習(xí)成本即可。很多時(shí)候,我們試圖改變團(tuán)隊(duì)的習(xí)慣去學(xué)習(xí)一個(gè)新的規(guī)范,所帶來的收益(投入產(chǎn)出比)甚微,那就得不償失了。

總結(jié)一下,定義好的規(guī)范的目的在于,降低學(xué)習(xí)成本,使得 API 盡可能通俗易懂。當(dāng)然,設(shè)計(jì)的 API?通俗易懂還有其他方式,例如我們定義的 API 的名字易于理解,API 的實(shí)現(xiàn)盡可能通用等。

二、探討 API 接口的兼容性

API 接口都是不斷演進(jìn)的。因此,我們需要在一定程度上適應(yīng)變化。在 RESTful API 中,API 接口應(yīng)該盡量兼容之前的版本。但是,在實(shí)際業(yè)務(wù)開發(fā)場景中,可能隨著業(yè)務(wù)需求的不斷迭代,現(xiàn)有的 API 接口無法支持舊版本的適配,此時(shí)如果強(qiáng)制升級服務(wù)端的 API 接口將導(dǎo)致客戶端舊有功能出現(xiàn)故障。實(shí)際上,Web 端是部署在服務(wù)器,因此它可以很容易為了適配服務(wù)端的新的 API 接口進(jìn)行版本升級,然而像 Android 端、IOS 端、PC 端等其他客戶端是運(yùn)行在用戶的機(jī)器上,因此當(dāng)前產(chǎn)品很難做到適配新的服務(wù)端的 API 接口,從而出現(xiàn)功能故障,這種情況下,用戶必須升級產(chǎn)品到最新的版本才能正常使用。為了解決這個(gè)版本不兼容問題,在設(shè)計(jì) RESTful API 的一種實(shí)用的做法是使用版本號。一般情況下,我們會在 url 中保留版本號,并同時(shí)兼容多個(gè)版本。

【GET】  /v1/users/{user_id}  // 版本 v1 的查詢用戶列表的 API 接口
【GET】  /v2/users/{user_id}  // 版本 v2 的查詢用戶列表的 API 接口

現(xiàn)在,我們可以不改變版本 v1 的查詢用戶列表的 API 接口的情況下,新增版本 v2 的查詢用戶列表的 API 接口以滿足新的業(yè)務(wù)需求,此時(shí),客戶端的產(chǎn)品的新功能將請求新的服務(wù)端的 API 接口地址。雖然服務(wù)端會同時(shí)兼容多個(gè)版本,但是同時(shí)維護(hù)太多版本對于服務(wù)端而言是個(gè)不小的負(fù)擔(dān),因?yàn)榉?wù)端要維護(hù)多套代碼。這種情況下,常見的做法不是維護(hù)所有的兼容版本,而是只維護(hù)最新的幾個(gè)兼容版本,例如維護(hù)最新的三個(gè)兼容版本。在一段時(shí)間后,當(dāng)絕大多數(shù)用戶升級到較新的版本后,廢棄一些使用量較少的服務(wù)端的老版本API 接口版本,并要求使用產(chǎn)品的非常舊的版本的用戶強(qiáng)制升級。注意的是,“不改變版本 v1 的查詢用戶列表的 API 接口”主要指的是對于客戶端的調(diào)用者而言它看起來是沒有改變。而實(shí)際上,如果業(yè)務(wù)變化太大,服務(wù)端的開發(fā)人員需要對舊版本的 API 接口使用適配器模式將請求適配到新的API 接口上。

有趣的是,GraphQL 提供不同的思路。GraphQL 為了解決服務(wù) API 接口爆炸的問題,以及將多個(gè) HTTP 請求聚合成了一個(gè)請求,提出只暴露單個(gè)服務(wù) API 接口,并且在單個(gè)請求中可以進(jìn)行多個(gè)查詢。GraphQL 定義了 API 接口,我們可以在前端更加靈活調(diào)用,例如,我們可以根據(jù)不同的業(yè)務(wù)選擇并加載需要渲染的字段。因此,服務(wù)端提供的全量字段,前端可以按需獲取。GraphQL 可以通過增加新類型和基于這些類型的新字段添加新功能,而不會造成兼容性問題。

此外,在使用 RPC API 過程中,我們特別需要注意兼容性問題,二方庫不能依賴 parent,此外,本地開發(fā)可以使用 SNAPSHOT,而線上環(huán)境禁止使用,避免發(fā)生變更,導(dǎo)致版本不兼容問題。我們需要為每個(gè)接口都應(yīng)定義版本號,保證后續(xù)不兼容的情況下可以升級版本。例如,Dubbo 建議第三位版本號通常表示兼容升級,只有不兼容時(shí)才需要變更服務(wù)版本。

關(guān)于規(guī)范的案例,我們可以看看 k8s 和 github,其中 k8s 采用了 RESTful API,而 github 部分采用了 GraphQL。

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/

https://developer.github.com/v4/

三、提供清晰的思維模型

所謂思維模型,我的理解是針對問題域抽象模型,對域模型的功能有統(tǒng)一認(rèn)知,構(gòu)建某個(gè)問題的現(xiàn)實(shí)映射,并劃分好模型的邊界,而域模型的價(jià)值之一就是統(tǒng)一思想,明確邊界。假設(shè),大家沒有清晰的思維模型,那么也不存在對 API 的統(tǒng)一認(rèn)知,那么就很可能出現(xiàn)下面圖片中的現(xiàn)實(shí)問題。

四、以抽象的方式屏蔽業(yè)務(wù)實(shí)現(xiàn)

我認(rèn)為好的 API 接口具有抽象性,因此需要盡可能的屏蔽業(yè)務(wù)實(shí)現(xiàn)。那么,問題來了,我們怎么理解抽象性?對此,我們可以思考?java.sql.Driver 的設(shè)計(jì)。這里,java.sql.Driver 是一個(gè)規(guī)范接口,而 com.mysql.jdbc.Driver
則是 mysql-connector-java-xxx.jar 對這個(gè)規(guī)范的實(shí)現(xiàn)接口。那么,切換成 Oracle 的成本就非常低了。

一般情況下,我們會通過 API 對外提供服務(wù)。這里,API 提供服務(wù)的接口的邏輯是固定的,換句話說,它具有通用性。但是,但我們遇到具有類似的業(yè)務(wù)邏輯的場景時(shí),即核心的主干邏輯相同,而細(xì)節(jié)的實(shí)現(xiàn)略有不同,那我們該何去何從?很多時(shí)候,我們會選擇提供多個(gè) API 接口給不同的業(yè)務(wù)方使用。事實(shí)上,我們可以通過 SPI 擴(kuò)展點(diǎn)來實(shí)現(xiàn)的更加優(yōu)雅。什么是 SPI?SPI 的英文全稱是 Serivce Provider Interface,即服務(wù)提供者接口,它是一種動態(tài)發(fā)現(xiàn)機(jī)制,可以在程序執(zhí)行的過程中去動態(tài)的發(fā)現(xiàn)某個(gè)擴(kuò)展點(diǎn)的實(shí)現(xiàn)類。因此,當(dāng) API 被調(diào)用時(shí)會動態(tài)加載并調(diào)用 SPI 的特定實(shí)現(xiàn)方法。

此時(shí),你是不是聯(lián)想到了模版方法模式。模板方法模式的核心思想是定義骨架,轉(zhuǎn)移實(shí)現(xiàn),換句話說,它通過定義一個(gè)流程的框架,而將一些步驟的具體實(shí)現(xiàn)延遲到子類中。事實(shí)上,在微服務(wù)的落地過程中,這種思想也給我們提供了非常好的理論基礎(chǔ)。

現(xiàn)在,我們來看一個(gè)案例:電商業(yè)務(wù)場景中的未發(fā)貨僅退款。這種情況在電商業(yè)務(wù)中非常場景,用戶下單付款后由于各種原因可能就申請退款了。此時(shí),因?yàn)椴簧婕巴素洠灾恍枰脩羯暾埻丝畈⑻顚懲丝钤颍缓笞屬u家審核退款。那么,由于不同平臺的退款原因可能不同,我們可以考慮通過 SPI 擴(kuò)展點(diǎn)來實(shí)現(xiàn)。

此外,我們還經(jīng)常使用工廠方法+策略模式來屏蔽外部的復(fù)雜性。例如,我們對外暴露一個(gè) API 接口?getTask(int operation),那么我們就可以通過工廠方法來創(chuàng)建實(shí)例,通過策略方法來定義不同的實(shí)現(xiàn)。

@Component
public class TaskManager {

    private static final Logger logger = LoggerFactory.getLogger(TaskManager.class);
    
    private static TaskManager instance;

    public MapInteger, ITask> taskMap = new HashMap();

    public static TaskManager getInstance() {
        return instance;
    }

    public ITask getTask(int operation) {
        return taskMap.get(operation);
    }

    /**
     * 初始化處理過程
     */
    @PostConstruct
    private void init() {
        logger.info("init task manager");
        instance = new TaskManager();
        // 單聊消息任務(wù)
        instance.taskMap.put(EventEnum.CHAT_REQ.getValue(), new ChatTask());
        // 群聊消息任務(wù)
        instance.taskMap.put(EventEnum.GROUP_CHAT_REQ.getValue(), new GroupChatTask());
        // 心跳任務(wù)
        instance.taskMap.put(EventEnum.HEART_BEAT_REQ.getValue(), new HeatBeatTask());
        
    }
}

還有一種屏蔽內(nèi)部復(fù)雜性設(shè)計(jì)就是外觀接口,它是將多個(gè)服務(wù)的接口進(jìn)行業(yè)務(wù)封裝與整合并提供一個(gè)簡單的調(diào)用接口給客戶端使用。這種設(shè)計(jì)的好處在于,客戶端不再需要知道那么多服務(wù)的接口,只需要調(diào)用這個(gè)外觀接口即可。但是,壞處也是顯而易見的,即增加了服務(wù)端的業(yè)務(wù)復(fù)雜度,接口性能不高,并且復(fù)用性不高。因此,因地制宜,盡可能保證職責(zé)單一,而在客戶端進(jìn)行“樂高式”組裝。如果存在 SEO 優(yōu)化的產(chǎn)品,需要被類似于百度這樣的搜索引擎收錄,可以當(dāng)首屏的時(shí)候,通過服務(wù)端渲染生成 HTML,使之讓搜索引擎收錄,若不是首屏的時(shí)候,可以通過客戶端調(diào)用服務(wù)端 RESTful API 接口進(jìn)行頁面渲染。

此外,隨著微服務(wù)的普及,我們的服務(wù)越來越多,許多較小的服務(wù)有更多的跨服務(wù)調(diào)用。因此,微服務(wù)體系結(jié)構(gòu)使得這個(gè)問題更加普遍。為了解決這個(gè)問題,我們可以考慮引入一個(gè)“聚合服務(wù)”,它是一個(gè)組合服務(wù),可以將多個(gè)微服務(wù)的數(shù)據(jù)進(jìn)行組合。這樣設(shè)計(jì)的好處在于,通過一個(gè)“聚合服務(wù)”將一些信息整合完后再返回給調(diào)用方。注意的是,“聚合服務(wù)”也可以有自己的緩存和數(shù)據(jù)庫。 事實(shí)上,聚合服務(wù)的思想無處不在,例如?Serverless 架構(gòu)。我們可以在實(shí)踐的過程中采用 AWS Lambda 作為 Serverless 服務(wù)背后的計(jì)算引擎,而 AWS Lambda 是一種函數(shù)即服務(wù)(Function-as-a-Servcie,F(xiàn)aaS)的計(jì)算服務(wù),我們直接編寫運(yùn)行在云上的函數(shù)。那么,這個(gè)函數(shù)可以組裝現(xiàn)有能力做服務(wù)聚合。

當(dāng)然,還有很多很好的設(shè)計(jì),我也會在陸續(xù)在公眾號中以續(xù)補(bǔ)的方式進(jìn)行補(bǔ)充與探討。

五、考慮背后的性能

我們需要考慮入?yún)⒆侄蔚母鞣N組合導(dǎo)致數(shù)據(jù)庫的性能問題。有的時(shí)候,我們可能暴露太多字段給外部組合使用,導(dǎo)致數(shù)據(jù)庫沒有相應(yīng)的索引而發(fā)生全表掃描。事實(shí)上,這種情況在查詢的場景特別常見。因此,我們可以只提供存在索引的字段組合給外部調(diào)用,或者在下面的案例中,要求調(diào)用方必填 taskId 和 caseId 來保證我們數(shù)據(jù)庫合理使用索引,進(jìn)一步保證服務(wù)提供方的服務(wù)性能。

ResultVoid> agree(Long taskId, Long caseId, Configger configger);

同時(shí),對于報(bào)表操作、批量操作、冷數(shù)據(jù)查詢等 API 應(yīng)該可以考慮異步能力。

此外,GraphQL 雖然解決將多個(gè) HTTP 請求聚合成了一個(gè)請求,但是 schema 會逐層解析方式遞歸獲取全部數(shù)據(jù)。例如分頁查詢的統(tǒng)計(jì)總條數(shù),原本 1 次可以搞定的查詢,演變成了 N + 1 次對數(shù)據(jù)庫查詢。此外,如果寫得不合理還會導(dǎo)致惡劣的性能問題,因此,我們在設(shè)計(jì)的過程中特別需要注意。

六、異常響應(yīng)與錯(cuò)誤機(jī)制

業(yè)內(nèi)對 RPC API 拋出異常,還是拋出錯(cuò)誤碼已經(jīng)有太多的爭論。《阿里巴巴 Java 開發(fā)手冊》建議:跨應(yīng)用 RPC 調(diào)用優(yōu)先考慮使用 isSuccess() 方法、“錯(cuò)誤碼”、“錯(cuò)誤簡短信息”。關(guān)于 RPC 方法返回方式使用 Result 方式的理由 : 1)使用拋異常返回方式,調(diào)用方如果沒有捕獲到,就會產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。2)如果不加棧信息,只是 new 自定義異常,加入自己的理解的 error message,對于調(diào)用端解決問題的幫助不會太多。如果加了棧信息,在頻繁調(diào)用出錯(cuò)的情況下,數(shù)據(jù)序列化和傳輸?shù)男阅軗p耗也是問題。當(dāng)然,我也支持這個(gè)論點(diǎn)的實(shí)踐擁護(hù)者。

public ResultXxxDTO> getXxx(String param) {
    try {
        // ...
        return Result.create(xxxDTO);
    } catch (BizException e) {
        log.error("...", e);
        return Result.createErrorResult(e.getErrorCode(), e.getErrorInfo(), true);
    }
}

在 Web API 設(shè)計(jì)過程中,我們會使用?ControllerAdvice 統(tǒng)一包裝錯(cuò)誤信息。而在微服務(wù)復(fù)雜的鏈?zhǔn)秸{(diào)用中,我們會比單體架構(gòu)更難以追蹤與定位問題。因此,在設(shè)計(jì)的時(shí)候,需要特別注意。一種比較好的方案是,當(dāng) RESTful API 接口出現(xiàn)非 2xx 的 HTTP 錯(cuò)誤碼響應(yīng)時(shí),采用全局的異常結(jié)構(gòu)響應(yīng)信息。其中,code 字段用來表示某類錯(cuò)誤的錯(cuò)誤碼,在微服務(wù)中應(yīng)該加上“{biz_name}/”前綴以便于定位錯(cuò)誤發(fā)生在哪個(gè)業(yè)務(wù)系統(tǒng)上。我們來看一個(gè)案例,假設(shè)“用戶中心”某個(gè)接口沒有權(quán)限獲取資源而出現(xiàn)錯(cuò)誤,我們的業(yè)務(wù)系統(tǒng)可以響應(yīng)“UC/AUTH_DENIED”,并且通過自動生成的 UUID 值的 request_id 字段,在日志系統(tǒng)中獲得錯(cuò)誤的詳細(xì)信息。

HTTP/1.1 400 Bad Request
Content-Type: application/json
{
   "code": "INVALID_ARGUMENT",
   "message": "{error message}",
   "cause": "{cause message}",
   "request_id": "01234567-89ab-cdef-0123-456789abcdef",
   "host_id": "{server identity}",
   "server_time": "2014-01-01T12:00:00Z"
}
七、思考 API 的冪等性

冪等機(jī)制的核心是保證資源唯一性,例如客戶端重復(fù)提交或服務(wù)端的多次重試只會產(chǎn)生一份結(jié)果。支付場景、退款場景,涉及金錢的交易不能出現(xiàn)多次扣款等問題。事實(shí)上,查詢接口用于獲取資源,因?yàn)樗皇遣樵償?shù)據(jù)而不會影響到資源的變化,因此不管調(diào)用多少次接口,資源都不會改變,所以是它是冪等的。而新增接口是非冪等的,因?yàn)檎{(diào)用接口多次,它都將會產(chǎn)生資源的變化。因此,我們需要在出現(xiàn)重復(fù)提交時(shí)進(jìn)行冪等處理。那么,如何保證冪等機(jī)制呢?事實(shí)上,我們有很多實(shí)現(xiàn)方案。其中,一種方案就是常見的創(chuàng)建唯一索引。在數(shù)據(jù)庫中針對我們需要約束的資源字段創(chuàng)建唯一索引,可以防止插入重復(fù)的數(shù)據(jù)。但是,遇到分庫分表的情況是,唯一索引也就不那么好使了,此時(shí),我們可以先查詢一次數(shù)據(jù)庫,然后判斷是否約束的資源字段存在重復(fù),沒有的重復(fù)時(shí)再進(jìn)行插入操作。注意的是,為了避免并發(fā)場景,我們可以通過鎖機(jī)制,例如悲觀鎖與樂觀鎖保證數(shù)據(jù)的唯一性。這里,分布式鎖是一種經(jīng)常使用的方案,它通常情況下是一種悲觀鎖的實(shí)現(xiàn)。但是,很多人經(jīng)常把悲觀鎖、樂觀鎖、分布式鎖當(dāng)作冪等機(jī)制的解決方案,這個(gè)是不正確的。除此之外,我們還可以引入狀態(tài)機(jī),通過狀態(tài)機(jī)進(jìn)行狀態(tài)的約束以及狀態(tài)跳轉(zhuǎn),確保同一個(gè)業(yè)務(wù)的流程化執(zhí)行,從而實(shí)現(xiàn)數(shù)據(jù)冪等。事實(shí)上,并不是所有的接口都要保證冪等,換句話說,是否需要冪等機(jī)制可以通過考量需不需要確保資源唯一性,例如行為日志可以不考慮冪等性。當(dāng)然,還有一種設(shè)計(jì)方案是接口不考慮冪等機(jī)制,而是在業(yè)務(wù)實(shí)現(xiàn)的時(shí)候通過業(yè)務(wù)層面來保證,例如允許存在多份數(shù)據(jù),但是在業(yè)務(wù)處理的時(shí)候獲取最新的版本進(jìn)行處理。

(完,轉(zhuǎn)載請注明作者及出處。)

寫在末尾

【服務(wù)端思維】:我們一起聊聊服務(wù)端核心技術(shù),探討一線互聯(lián)網(wǎng)的項(xiàng)目架構(gòu)與實(shí)戰(zhàn)經(jīng)驗(yàn)。同時(shí),擁有眾多技術(shù)大牛的「后端圈」大家庭,期待你的加入,一群同頻者,一起成長,一起精進(jìn),打破認(rèn)知的局限性。

更多精彩文章,盡在「服務(wù)端思維」!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/74520.html

相關(guān)文章

  • 人人都是 API 設(shè)計(jì)師我對 RESTful APIGraphQLRPC API 思考

    摘要:通常情況下,偽都是基于第一層次與第二層次設(shè)計(jì)的。為了解決這個(gè)版本不兼容問題,在設(shè)計(jì)的一種實(shí)用的做法是使用版本號。例如,建議第三位版本號通常表示兼容升級,只有不兼容時(shí)才需要變更服務(wù)版本。 原文地址:梁桂釗的博客 博客地址:blog.720ui.com 歡迎關(guān)注公眾號:「服務(wù)端思維」。一群同頻者,一起成長,一起精進(jìn),打破認(rèn)知的局限性。 有一段時(shí)間沒怎么寫文章了,今天提筆寫一篇自己對 API 設(shè)...

    ormsf 評論0 收藏0
  • GraphQL:一種更高效、強(qiáng)大和靈活數(shù)據(jù)提供方式

    摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...

    waruqi 評論0 收藏0
  • GraphQL:一種更高效、強(qiáng)大和靈活數(shù)據(jù)提供方式

    摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...

    zzbo 評論0 收藏0
  • GraphQL:一種更高效、強(qiáng)大和靈活數(shù)據(jù)提供方式

    摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...

    eccozhou 評論0 收藏0
  • GraphQL:一種更高效、強(qiáng)大和靈活數(shù)據(jù)提供方式

    摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...

    DTeam 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<