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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

干掉RESTful:GraphQL真香!

發(fā)布時間:2024/4/11 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 干掉RESTful:GraphQL真香! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

點擊上方“朱小廝的博客”,選擇“設為星標”

后臺回復"書",獲取近百本電子書入口

封面:重慶洪崖洞

來源:http://suo.im/5W1XNE

REST作為一種現(xiàn)代網(wǎng)絡應用非常流行的軟件架構(gòu)風格,自從Roy Fielding博士在2000年他的博士論文中提出來到現(xiàn)在已經(jīng)有了20年的歷史。它的簡單易用性,可擴展性,伸縮性受到廣大Web開發(fā)者的喜愛。

REST 的 API 配合JSON格式的數(shù)據(jù)交換,使得前后端分離、數(shù)據(jù)交互變得非常容易,而且也已經(jīng)成為了目前Web領域最受歡迎的軟件架構(gòu)設計模式。

但隨著REST API的流行和發(fā)展,它的缺點也暴露了出來:

  • 濫用REST接口,導致大量相似度很高(具有重復性)的API越來越冗余。

  • 對于前端而言:REST API粒度較粗,難以一次性符合前端的數(shù)據(jù)要求,前端需要分多次請求接口數(shù)據(jù)。增加了前端人員的工作量。

  • 對于后端而言:前端需要的數(shù)據(jù)往往在不同的地方具有相似性,但卻又不同,比如針對同樣的用戶信息,有的地方只需要用戶簡要信息(比如頭像、昵稱),有些地方需要詳細的信息,這就需要開發(fā)不同的接口來滿足這些需求。當這樣的相似但又不同的地方多的時候,就需要開發(fā)更多的接口來滿足前端的需要。增加了后端開發(fā)人員的工作量和重復度。

那我們來分析一下,當前端需求變化,涉及到改動舊需求時,會有以下這些情況:

做加法:

產(chǎn)品需求增加,頁面需要增加功能,數(shù)據(jù)也就相應的要增加顯示,那么REST接口也需要做增加,這種無可厚非。

做減法:

產(chǎn)品需求減少,頁面需要減少功能,或者減少某些信息顯示,那么數(shù)據(jù)就要做減法。

一種通常懶惰的做法是,前端不與后端溝通,僅在前端對數(shù)據(jù)選擇性顯示。

因為后端接口能夠滿足數(shù)據(jù)需要,僅僅是在做顯示的時候?qū)?shù)據(jù)進行了選擇性顯示,但接口的數(shù)據(jù)是存在冗余的,這種情況一個是存在數(shù)據(jù)泄露風險,另外就是數(shù)據(jù)量過大時造成網(wǎng)絡流量過大,頁面加載緩慢,用戶流量費白白消耗,用戶體驗就會下降。

另外一種做法就是告知后端,要么開發(fā)新的接口,要么,修改舊接口,刪掉冗余字段。

但一般來說,開發(fā)新接口往往是后端開發(fā)人員會選擇的方案,因為這個方案對現(xiàn)有系統(tǒng)的影響最低,不會有額外的風險。

修改舊接口刪除冗余數(shù)據(jù)的方案往往開發(fā)人員不會選擇,這是為什么呢?

這就涉及到了系統(tǒng)的穩(wěn)定性問題了,舊接口往往不止是一個地方在用,很有可能很多頁面、設置不同客戶端、不同服務都調(diào)用了這個接口獲取數(shù)據(jù),不做詳細的調(diào)查,是不可能知道到底舊接口被調(diào)用了多少次,一旦改動舊接口,涉及范圍可能非常大,往往會引起其他地方出現(xiàn)崩潰。改動舊接口成本太高,所以往往不會被采取。

同時做加減法:

既有加法,又有減法,其實這種就跟新需求沒啥區(qū)別,前端需要重做頁面,后端需要新寫接口滿足前端需要,但是舊接口還是不能輕舉妄動(除非確定只有這一處調(diào)用才可以刪除)。

往往這個時候,其實用到的數(shù)據(jù)大多都是來自于同一個DO或者DTO,不過是在REST接口組裝數(shù)據(jù)時,用不同的VO來封裝不同字段,或者,使用同樣的VO,組裝數(shù)據(jù)時做刪減。

看到這些問題是不是覺得令人頭大?

所以需求頻繁改動是萬惡之源,當產(chǎn)品小哥哥改動需求時,程序員小哥哥可能正提著鐵鍬趕來......

那么有沒有一種方案或者框架,可以使得在用到同一個領域模型(DO或者DTO)的數(shù)據(jù)時,前端對于這個模型的數(shù)據(jù)字段需求的改動,后端可以根據(jù)前端的改動和需要,自動適配,自動組裝需要的字段,返回給前端呢?如果能這樣做的話,那么后端程序猿小哥可能要開心死了,前端妹子也不用那么苦口婆心地勸說后端小哥哥了。

所以GraphQL隆重出世了!那么問題來了!


Part 1 What is GraphQL

GraphQL簡介

  • GraphQL是一種新的API標準,它提供了一種比REST更有效、更強大和更靈活的替代方案。

  • 它是由Facebook開發(fā)并開源的,現(xiàn)在由來自世界各地的公司和個人組成的大型社區(qū)維護。

  • GraphQL本質(zhì)上是一種基于api的查詢語言,現(xiàn)在大多數(shù)應用程序都需要從服務器中獲取數(shù)據(jù),這些數(shù)據(jù)存儲可能存儲在數(shù)據(jù)庫中,API的職責是提供與應用程序需求相匹配的存儲數(shù)據(jù)的接口。

  • 它是數(shù)據(jù)庫無關的,而且可以在使用API的任何環(huán)境中有效使用,我們可以理解為GraphQL是基于API之上的一層封裝,目的是為了更好,更靈活的適用于業(yè)務的需求變化。

簡單的來說,它

它的工作模式是這樣子的:

GraphQL 對比 REST API 有什么好處?

REST API 的接口靈活性差、接口操作流程繁瑣,GraphQL 的聲明式數(shù)據(jù)獲取,使得接口數(shù)據(jù)精確返回,數(shù)據(jù)查詢流程簡潔,照顧了客戶端的靈活性。

客戶端拓展功能時要不斷編寫新接口(依賴于服務端),GraphQL 中一個服務僅暴露一個 GraphQL 層,消除了服務器對數(shù)據(jù)格式的硬性規(guī)定,客戶端按需請求數(shù)據(jù),可進行單獨維護和改進。

REST API 基于HTTP協(xié)議,不能靈活選擇網(wǎng)絡協(xié)議,而傳輸層無關、數(shù)據(jù)庫技術無關使得 GraphQL 有更加靈活的技術棧選擇,能夠?qū)崿F(xiàn)在網(wǎng)絡協(xié)議層面優(yōu)化應用。

舉個經(jīng)典的例子:前端向后端請求一個book對象的數(shù)據(jù)及其作者信息。我用動圖來分別演示下REST和GraphQL是怎么樣的一個過程。先看REST API的做法:

REST API獲取數(shù)據(jù)

再來看GraphQL是怎么做的:

GraphQL獲取數(shù)據(jù)

可以看出其中的區(qū)別:

與REST多個endpoint不同,每一個的 GraphQL 服務其實對外只提供了一個用于調(diào)用內(nèi)部接口的端點,所有的請求都訪問這個暴露出來的唯一端點。

Endpoints對比

REST API's Endpoints

GraphQL 實際上將多個 HTTP 請求聚合成了一個請求,將多個 restful 請求的資源變成了一個從根資源 POST 訪問其他資源的 Comment 和 Author 的圖,多個請求變成了一個請求的不同字段,從原有的分散式請求變成了集中式的請求,因此GraphQL又可以被看成是圖數(shù)據(jù)庫的形式。

圖數(shù)據(jù)庫模式的數(shù)據(jù)查詢

那我們已經(jīng)能看到GraphQL的先進性,接下來看看它是怎么做的。

GraphQL 思考模式

使用GraphQL接口設計獲取數(shù)據(jù)需要三步:

GraphQL獲取數(shù)據(jù)三步驟

1、首先要設計數(shù)據(jù)模型,用來描述數(shù)據(jù)對象,它的作用可以看做是VO,用于告知GraphQL如何來描述定義的數(shù)據(jù),為下一步查詢返回做準備;

2、前端使用模式查詢語言(Schema)來描述需要請求的數(shù)據(jù)對象類型和具體需要的字段(稱之為聲明式數(shù)據(jù)獲取);

3、后端GraphQL通過前端傳過來的請求,根據(jù)需要,自動組裝數(shù)據(jù)字段,返回給前端。

GraphQL的這種思考模式是不是完美解決了之前遇到的問題呢?先總結(jié)它的好處:

在它的設計思想中,GraphQL 以圖的形式將整個 Web 服務中的資源展示出來,客戶端可以按照其需求自行調(diào)用,類似添加字段的需求其實就不再需要后端多次修改了。

創(chuàng)建GraphQL服務器的最終目標是:允許查詢通過圖和節(jié)點的形式去獲取數(shù)據(jù)。


GraphQL執(zhí)行邏輯

有人會問:

  • 使用了GraphQL就要完全拋棄REST了嗎?

  • GraphQL需要直接對接數(shù)據(jù)庫嗎?

  • 使用GraphQL需要對現(xiàn)有的后端服務進行大刀闊斧的修改嗎?

答案是:NO!不需要!

它完全可以以一種不侵入的方式來部署,將它作為前后端的中間服務,也就是,現(xiàn)在開始逐漸流行的?前端 —— 中端 —— 后端?的三層結(jié)構(gòu)模式來部署!

那就來看一下這樣的部署模式圖:

GraphQL執(zhí)行邏輯

也就是說,完全可以搭建一個GraphQL服務器,專門來處理前端請求,并處理后端服務獲取的數(shù)據(jù),重新進行組裝、篩選、過濾,將完美符合前端需要的數(shù)據(jù)返回。

新的開發(fā)需求可以直接就使用GraphQL服務來獲取數(shù)據(jù)了,以前已經(jīng)上線的功能無需改動,還是使用原有請求調(diào)用REST接口的方式,最低程度的降低更換GraphQL帶來的技術成本問題!

如果沒有那么多成本來支撐改造,那么就不需要改造!

只有當原有需求發(fā)生變化,需要對原功能進行修改時,就可以換成GraphQL了。

GraphQL應用的基本架構(gòu)

下圖是一個 GraphQL 應用的基本架構(gòu),其中客戶端只和 GraphQL 層進行 API 交互,而 GraphQL 層再往后接入各種數(shù)據(jù)源。這樣一來,只要是數(shù)據(jù)源有的數(shù)據(jù), GraphQL 層都可以讓客戶端按需獲取,不必專門再去定接口了。

GraphQL應用基本架構(gòu)

一個GraphQL服務僅暴露一個 GraphQL Endpoint,可以按照業(yè)務來進行區(qū)分,部署多個GraphQL服務,分管不同的業(yè)務數(shù)據(jù),這樣就可以避免單服務器壓力過大的問題了。

GraphQL特點總結(jié)

  • 聲明式數(shù)據(jù)獲取(可以對API進行查詢):?聲明式的數(shù)據(jù)查詢帶來了接口的精確返回,服務器會按數(shù)據(jù)查詢的格式返回同樣結(jié)構(gòu)的 JSON 數(shù)據(jù)、真正照顧了客戶端的靈活性。

  • 一個微服務僅暴露一個 GraphQL 層:一個微服務只需暴露一個GraphQL endpoint,客戶端請求相應數(shù)據(jù)只通過該端點按需獲取,不需要再額外定義其他接口。

  • 傳輸層無關、數(shù)據(jù)庫技術無關:帶來了更靈活的技術棧選擇,比如我們可以選擇對移動設備友好的協(xié)議,將網(wǎng)絡傳輸數(shù)據(jù)量最小化,實現(xiàn)在網(wǎng)絡協(xié)議層面優(yōu)化應用。


Part 2 Schema & Type

GraphQL支持的數(shù)據(jù)操作

GraphQL對數(shù)據(jù)支持的操作有:

  • 查詢(Query):獲取數(shù)據(jù)的基本查詢。

  • 變更(Mutation):支持對數(shù)據(jù)的增刪改等操作。

  • 訂閱(Subscription):用于監(jiān)聽數(shù)據(jù)變動、并靠websocket等協(xié)議推送變動的消息給對方。

GraphQL支持的操作

GraphQL的核心概念:圖表模式(Schema)

要想要設計GraphQL的數(shù)據(jù)模型,用來描述你的業(yè)務數(shù)據(jù),那么就必須要有一套Schema語法來做支撐。

想要描述數(shù)據(jù),就必須離不開數(shù)據(jù)類型的定義。所以GraphQL設計了一套Schema模式(可以理解為語法),其中最重要的就是數(shù)據(jù)類型的定義和支持。

那么類型(Type)就是模式(Schema)最核心的東西了。

什么是類型?

  • 對于數(shù)據(jù)模型的抽象是通過類型(Type)來描述的,每一個類型有若干字段(Field)組成,每個字段又分別指向某個類型(Type)。這很像Java、C#中的類(Class)。

  • GraphQL的Type簡單可以分為兩種,一種叫做Scalar Type(標量類型),另一種叫做Object Type(對象類型)。

那么就分別來介紹下兩種類型。

標量類型(Scalar Type)

標量是GraphQL類型系統(tǒng)中最小的顆粒。類似于Java、C#中的基本類型。

其中內(nèi)建標量主要有:

  • String

  • Int

  • Float

  • Boolean

  • Enum

  • ID

Scalar Type

上面的類型僅僅是GraphQL默認內(nèi)置的類型,當然,為了保證最大的靈活性,GraphQL還可以很靈活的自行創(chuàng)建標量類型。

對象類型(Object Type)

僅有標量類型是不能滿足復雜抽象數(shù)據(jù)模型的需要,這時候我們可以使用對象類型。

通過對象模型來構(gòu)建GraphQL中關于一個數(shù)據(jù)模型的形狀,同時還可以聲明各個模型之間的內(nèi)在關聯(lián)(一對多、一對一或多對多)。

對象類型的定義可以參考下圖:

對象模型引入關聯(lián)關系

是不是很方便呢?我們可以像設計類圖一樣來設計GraphQL的對象模型。

類型修飾符(Type Modifier)

那么,類型系統(tǒng)僅僅只有類型定義是不夠的,我們還需要對類型進行更廣泛性的描述。

類型修飾符就是用來修飾類型,以達到額外的數(shù)據(jù)類型要求控制。

比如:

  • 列表:[Type]

  • 非空:Type!

  • 列表非空:[Type]!

  • 非空列表,列表內(nèi)容類型非空:[Type!]!

在描述數(shù)據(jù)模型(模式Schema)時,就可以對字段施加限制條件。

例如定義了一個名為User的對象類型,并對其字段進行定義和施加限制條件:

User字段控制

那么,返回數(shù)據(jù)時,像下面這種情況就是不允許的:

錯誤的表示

Graphql會根據(jù)Schema Type來自動返回正確的數(shù)據(jù):

正確的表示

其他類型

除了上面的,Graphql還有一些其他類型來更好的引入面向?qū)ο蟮脑O計思想:

接口類型(Interfaces):其他對象類型實現(xiàn)接口必須包含接口所有的字段,并具有相同的類型修飾符,才算實現(xiàn)接口。

比如定義了一個接口類型:

那么就可以實現(xiàn)該接口:

聯(lián)合類型(Union Types):聯(lián)合類型和接口十分相似,但是它并不指定類型之間的任何共同字段。幾個對象類型共用一個聯(lián)合類型。

輸入類型(Input Types):更新數(shù)據(jù)時有用,與常規(guī)對象只有關鍵字修飾不一樣,常規(guī)對象時?type?修飾,輸入類型是?input?修飾。

比如定義了一個輸入類型:

前端發(fā)送變更請求時就可以使用(通過參數(shù)來指定輸入的類型):

所以,這樣面向?qū)ο蟮脑O計方式,真的對后端開發(fā)人員特別友好!而且前端MVVM框架流行以來,面向?qū)ο蟮脑O計思想也越來越流行,前端使用Graphql也會得心應手。


Part 3 GraphQL技術接入架構(gòu)

Graphql 技術接入架構(gòu)

那么,該怎么設計來接入我們現(xiàn)有的系統(tǒng)中呢?

將Graphql服務直連數(shù)據(jù)庫的方式:最簡潔的配置,直接操作數(shù)據(jù)庫能減少中間環(huán)節(jié)的性能消耗。

直連數(shù)據(jù)庫的接入

集成現(xiàn)有服務的GraphQL層:這種配置適合于舊服務的改造,尤其是在涉及第三方服務時、依然可以通過原有接口進行交互。

集成現(xiàn)有服務的GraphQL層

直連數(shù)據(jù)庫和集成服務的混合模式:前兩種方式的混合。

混合接入方式

可以說是非常靈活了!你都不用擔心會給你帶來任何的麻煩。


服務端實現(xiàn)

在服務端, GraphQL 服務器可用任何可構(gòu)建 Web 服務器的語言實現(xiàn)。有以下語言的實現(xiàn)供參考:

C# / .NET、Clojure、Elixir、Erlang、Go、Groovy、Java、JavaScript、Julia、Kotlin、Perl、PHP、Python、R、Ruby、Rust、Scala、Swift... 種類繁多,幾乎流行的語言都有支持。

客戶端實現(xiàn)

在客戶端,Graphql Client目前有下面的語言支持:C# / .NET、Clojurescript、Elm、Flutter、Go、Java / Android、JavaScript、Julia、Swift / Objective-C、iOS、Python、R。覆蓋了眾多客戶端設計語言,而其他語言的支持也在推進中。

想知道更多?描下面的二維碼關注我

后臺回復"書",獲取近百本電子書入口

【精彩推薦】

  • 超清晰的DNS入門指南

  • 深入理解Java Stream流水線

  • 干掉Swagger,試試這個

  • 干掉GuavaCache:Caffeine才是本地緩存的王

  • 如何用ELK搭建TB級的日志系統(tǒng)

  • 深度好文:Linux系統(tǒng)內(nèi)存知識

  • 日志系統(tǒng)新貴Loki,確實比笨重的ELK輕

  • 日志采集系統(tǒng)都用到哪些技術?

  • 面試官:為什么HashMap的加載因子是0.75?

點個贊+在看,少個 bug?????

總結(jié)

以上是生活随笔為你收集整理的干掉RESTful:GraphQL真香!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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