日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

精读《REST,GraphQL,Webhooks gRPC 如何选型》

發(fā)布時(shí)間:2025/3/20 编程问答 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 精读《REST,GraphQL,Webhooks gRPC 如何选型》 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 引言

每當(dāng)項(xiàng)目進(jìn)入聯(lián)調(diào)階段,或者提前約定接口時(shí),前后端就會(huì)聚在一起熱火朝天的討論起來。可能 99% 的場景都在約定 Http 接口,討論 URL 是什么,入?yún)⑹鞘裁?#xff0c;出參是什么。

有的團(tuán)隊(duì)前后端接口約定更加高效,后端會(huì)拿出接口定義代碼,前端會(huì)轉(zhuǎn)換成(或自動(dòng)轉(zhuǎn)成)Typescript 定義文件。

但這些工作都針對(duì)于 Http 接口,今天通過 when-to-use-what-rest-graphql-webhooks-grpc 一文,拋開聯(lián)調(diào)時(shí)千遍一律的 Http 接口,一起看看接口還可以怎么約定,分別適用于哪些場景,你現(xiàn)在處于哪個(gè)場景。

2 概述

本文主要講了四種接口設(shè)計(jì)方案,分別是:REST、gRPC、GraphQL、Webhooks,下面分別介紹一下。

REST

REST 也許是最通用,也是最常用的接口設(shè)計(jì)方案,它是 無狀態(tài)的,以資源為核心,針對(duì)如何操作資源定義了一系列 URL 約定,而操作類型通過 GET POST PUT DELETE 等 HTTP Methods 表示。

REST 基于原生 HTTP 接口,因此改造成本很小,而且其無狀態(tài)的特性,降低了前后端耦合程度,利于快速迭代。

隨著未來發(fā)展,REST 可能更適合提供微服務(wù) API。

使用舉例:

  • curl -v -X GET https://api.sandbox.paypal.com/v1/activities/activities?start_time=2012-01-01T00:00:01.000Z&end_time=2014-10-01T23:59:59.999Z&page_size=10 \

  • -H "Content-Type: application/json" \

  • -H "Authorization: Bearer Access-Token"

  • gRPC

    gRPC 是對(duì) RPC 的一個(gè)新嘗試,最大特點(diǎn)是使用 protobufs 語言格式化數(shù)據(jù)。

    RPC 主要用來做服務(wù)器之間的方法調(diào)用,影響其性能最重要因素就是 序列化/反序列化 效率。RPC 的目的是打造一個(gè)高效率、低消耗的服務(wù)調(diào)用方式,因此比較適合 IOT 等對(duì)資源、帶寬、性能敏感的場景。而 gRPC 利用 protobufs 進(jìn)一步提高了序列化速度,降低了數(shù)據(jù)包大小。

    使用舉例:

    gRPC 主要用于服務(wù)之間傳輸,這里拿 Nodejs 舉例:

    1.定義接口。由于 gRPC 使用 protobufs,所以接口定義文件就是 helloword.proto

  • // The greeting service definition.

  • service Greeter {

  • ?// Sends a greeting

  • ?rpc SayHello (HelloRequest) returns (HelloReply) {}

  • ?// Sends another greeting

  • ?rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}

  • }

  • // The request message containing the user's name.

  • message HelloRequest {

  • ?string name = 1;

  • }

  • // The response message containing the greetings

  • message HelloReply {

  • ?string message = 1;

  • }

  • 這里定義了服務(wù) Greeter,擁有兩個(gè)方法: SayHelloSayHelloAgain,通過 message 關(guān)鍵字定義了入?yún)⑴c出參的結(jié)構(gòu)。

    事實(shí)上利用 protobufs,傳輸數(shù)據(jù)時(shí)僅傳送很少的內(nèi)容,作為代價(jià),雙方都要知道接口定義規(guī)則才能序列化/反序列化。

    2.定義服務(wù)器:

  • function sayHello(call, callback) {

  • ?callback(null, { message: "Hello " + call.request.name });

  • }

  • function sayHelloAgain(call, callback) {

  • ?callback(null, { message: "Hello again, " + call.request.name });

  • }

  • function main() {

  • ?var server = new grpc.Server();

  • ?server.addProtoService(hello_proto.Greeter.service, {

  • ? ?sayHello: sayHello,

  • ? ?sayHelloAgain: sayHelloAgain

  • ?});

  • ?server.bind("0.0.0.0:50051", grpc.ServerCredentials.createInsecure());

  • ?server.start();

  • }

  • 我們?cè)?50051 端口支持了 gRPC 服務(wù),并注冊(cè)了服務(wù) Greeter,并對(duì) sayHello sayHelloAgain 方法做了一些業(yè)務(wù)處理,并返回給調(diào)用方一些數(shù)據(jù)。

    3.定義客戶端:

  • function main() {

  • ?var client = new hello_proto.Greeter(

  • ? ?"localhost:50051",

  • ? ?grpc.credentials.createInsecure()

  • ?);

  • ?client.sayHello({ name: "you" }, function(err, response) {

  • ? ?console.log("Greeting:", response.message);

  • ?});

  • ?client.sayHelloAgain({ name: "you" }, function(err, response) {

  • ? ?console.log("Greeting:", response.message);

  • ?});

  • }

  • 可以看到,客戶端和服務(wù)端同時(shí)需要拿到 proto 結(jié)構(gòu),客戶端數(shù)據(jù)發(fā)送也要依賴 proto 包提供的方法,框架會(huì)內(nèi)置做掉序列化/反序列化的工作。

    也有一些額外手段將 gRPC 轉(zhuǎn)換為 http 服務(wù),讓網(wǎng)頁端也享受到其高效、低耗的好處。但是不要忘了,RPC 最常用的場景是 IOT 等硬件領(lǐng)域,網(wǎng)頁場景也許不會(huì)在乎節(jié)省幾 KB 的流量。

    GraphQL

    GraphQL 不是 REST 的替代品,而是另一種交互形式:前端決定后端的返回結(jié)果。

    GraphQL 帶來的最大好處是精簡請(qǐng)求響應(yīng)內(nèi)容,不會(huì)出現(xiàn)冗余字段,前端可以決定后端返回什么數(shù)據(jù)。但要注意的是,前端的決定權(quán)取決于后端支持什么數(shù)據(jù),因此 GraphQL 更像是精簡了返回值的 REST,而后端接口也可以一次性定義完所有功能,而不需要逐個(gè)開發(fā)。

    再次強(qiáng)調(diào),相比 REST 和 gRPC,GraphQL 是由前端決定返回結(jié)果的反模式。

    使用舉例:

    原文推薦參考 GitHub GraphQL API

    比如查詢某個(gè)組織下的成員,REST 風(fēng)格接口可能是:

  • curl -v https://api.github.com/orgs/:org/members

  • 含義很明確,但問題是返回結(jié)果不明確,必須實(shí)際調(diào)試才知道。換成等價(jià)的 GraphQL 是這樣的:

  • query {

  • ?organization(login: "github") {

  • ? ?members(first: 100) {

  • ? ? ?edges {

  • ? ? ? ?node {

  • ? ? ? ? ?name

  • ? ? ? ? ?avatarUrl

  • ? ? ? ?}

  • ? ? ?}

  • ? ?}

  • ?}

  • }

  • 返回的結(jié)果和約定的格式結(jié)構(gòu)一致,且不會(huì)有多余的字段:

  • {

  • ?"data": {

  • ? ?"organization": {

  • ? ? ?"members": {

  • ? ? ? ?"edges": [

  • ? ? ? ? ?{

  • ? ? ? ? ? ?"node": {

  • ? ? ? ? ? ? ?"name": "Chris Wanstrath",

  • ? ? ? ? ? ? ?"avatarUrl": "https://avatars0.githubusercontent.com/u/2?v=4"

  • ? ? ? ? ? ?}

  • ? ? ? ? ?},

  • ? ? ? ? ?{

  • ? ? ? ? ? ?"node": {

  • ? ? ? ? ? ? ?"name": "Justin Palmer",

  • ? ? ? ? ? ? ?"avatarUrl": "https://avatars3.githubusercontent.com/u/25?v=4"

  • ? ? ? ? ? ?}

  • ? ? ? ? ?}

  • ? ? ? ?]

  • ? ? ?}

  • ? ?}

  • ?}

  • }

  • 但是能看出來,這樣做需要一個(gè)系統(tǒng)幫助你寫 query,很多框架都提供這個(gè)功能,比如 apollo-client。

    Webhooks

    如果說 GraphQL 顛覆了前后端交互模式,那 Webhooks 可以說是徹頭徹尾的反模式了,因?yàn)槠涠x就是,前端不主動(dòng)發(fā)送請(qǐng)求,完全由后端推送。

    它最適合解決輪詢問題。或者說輪詢就是一種妥協(xié)的行為,當(dāng)后端不支持 Webhooks 模式時(shí)。

    使用舉例:

    Webhooks 本身也可以由 REST 或者 gRPC 實(shí)現(xiàn),所以就不貼代碼了。舉個(gè)常用例子,比如你的好友發(fā)了一條朋友圈,后端將這條消息推送給所有其他好友的客戶端,就是 Webhooks 的典型場景。

    最后作者給出的結(jié)論是,這四個(gè)場景各有不同使用場景,無法相互替代:

    • REST:無狀態(tài)的數(shù)據(jù)傳輸結(jié)構(gòu),適用于通用、快速迭代和標(biāo)準(zhǔn)化語義的場景。

    • gRPC:輕量的傳輸方式,特殊適合對(duì)性能高要求或者環(huán)境苛刻的場景,比如 IOT。

    • GraphQL: 請(qǐng)求者可以自定義返回格式,某些程度上可以減少前后端聯(lián)調(diào)成本。

    • Webhooks: 推送服務(wù),主要用于服務(wù)器主動(dòng)更新客戶端資源的場景。

    3 精讀

    REST 并非適用所有場景

    本文給了我們一個(gè)更大的視角看待日常開發(fā)中的接口問題,對(duì)于奮戰(zhàn)在一線的前端同學(xué),接觸到 90% 的接口都是非 REST 規(guī)則的 Http 接口,能真正落實(shí) REST 的團(tuán)隊(duì)其實(shí)非常少。這其實(shí)暴露了一個(gè)重要問題,就是 REST 所帶來的好處,在整套業(yè)務(wù)流程中到底占多大的比重?

    不僅接口設(shè)計(jì)方案的使用要分場景,針對(duì)某個(gè)接口方案的重要性也要再繼續(xù)細(xì)分:在做一個(gè)開放接口的項(xiàng)目,提供 Http 接口給第三方使用,這時(shí)必須好好規(guī)劃接口的語義,所以更容易讓大家達(dá)成一致使用 REST 約定;而開發(fā)一個(gè)產(chǎn)品時(shí),其實(shí)前后端不關(guān)心接口格式是否規(guī)范,甚至在開發(fā)內(nèi)網(wǎng)產(chǎn)品時(shí),性能和冗余都不會(huì)考慮,效率放在了第一位。所以第一點(diǎn)啟示是,不要埋冤當(dāng)前團(tuán)隊(duì)業(yè)務(wù)為什么沒有使用某個(gè)更好的接口約定,因?yàn)榻涌诩s定很可能是業(yè)務(wù)形態(tài)決定的,而不是憑空做技術(shù)對(duì)比從而決定的。

    gRPC 是服務(wù)端交互的首選

    前端同學(xué)轉(zhuǎn) node 開發(fā)時(shí),很喜歡用 Http 方式進(jìn)行服務(wù)器間通訊,但可能會(huì)疑惑,為什么公司內(nèi)部 Java 或者 C++ 寫的服務(wù)都不提供 Http 方式調(diào)用,而是另外一個(gè)名字。了解 gRPC 后,可以認(rèn)識(shí)到這些平臺(tái)都是對(duì) RPC 方式的封裝,服務(wù)器間通信對(duì)性能和延時(shí)要求非常高,所以比較適合專門為性能優(yōu)化的 gRPC 等服務(wù)。

    GraphQL 需要配套

    GraphQL 不是 REST 的替代品,所以不要想著團(tuán)隊(duì)從 Http 接口遷移到 GraphQL 就能提升 X% 的開發(fā)效率。GraphQL 方案是一種新的前后端交互約定,所以上手成本會(huì)比較高,同時(shí),為了方便前端同學(xué)拼 query,等于把一部分后端工作量轉(zhuǎn)移給了前端,如果此時(shí)沒有一個(gè)足夠好用的平臺(tái)快速查閱、生成、維護(hù)這些定義,開發(fā)效率可能不升反降。

    總的來說,對(duì)外開放 API 或者擁有完整配套的場景,使用 GraphQL 是比較理想的,但對(duì)于快速迭代,平臺(tái)又不夠成熟的團(tuán)隊(duì),繼續(xù)使用標(biāo)準(zhǔn) Http 接口可以更快完成項(xiàng)目。

    Webhooks 解決特殊場景問題

    對(duì)于第三方平臺(tái)驗(yàn)權(quán)、登陸等 沒有前端界面做中轉(zhuǎn)的場景,或者強(qiáng)安全要求的支付場景等,適合用 Webhooks 做數(shù)據(jù)主動(dòng)推送。說白了就是在前端無從參與,或者因?yàn)榍岸税踩珕栴}不適合參與時(shí),就是 Webhooks 的場景。很顯然 Webhooks 也不是 Http 的替代品,不過的確是一種新的前后端交互方式。

    對(duì)于慢查詢等場景,前端普遍使用輪詢完成,這和 Socket 相比體驗(yàn)更弱,但無狀態(tài)的特性反而會(huì)降低服務(wù)器負(fù)擔(dān),所以慢查詢和即時(shí)通訊要區(qū)分對(duì)待,用戶對(duì)消息及時(shí)性的敏感程度決定了使用哪種方案。

    4 總結(jié)

    最后,上面總結(jié)的內(nèi)容一定還有許多疏漏,歡迎補(bǔ)充。

    5 更多討論

    討論地址是:精讀《REST, GraphQL, Webhooks, & gRPC 如何選型》 · Issue #102 · dt-fe/weekly


    原文發(fā)布時(shí)間為:2018-11-03 本文作者:黃子毅??

    本文來自云棲社區(qū)合作伙伴“前端大學(xué)”,了解相關(guān)信息可以關(guān)注“前端大學(xué)”。

    總結(jié)

    以上是生活随笔為你收集整理的精读《REST,GraphQL,Webhooks gRPC 如何选型》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。