GraphQL這個坑可以入了 (2)新協議的優勢 - 所求即所得

GraphQL被開源出來其實只是這一兩年的事,但是Facebook使用這個技術已經有四五年的歷史了,所以說這是一個相對成熟的技術。另外,自從GraphQL被公開出來之後,這個社區異常活躍。就連Facebook里的GraphQL 的原始設計者們,他們自己都好驚奇,突然間就有了很多Facebook以外的人,開始使用GraphQL。那我們今天就來看看它有什麼好。

那我們先來看看GraphQL的查詢什麼樣,先來個直觀的認識,下面就是一個GraphQL查詢,去拿到id為9527的用戶,但與與/user/:id這種Rest查詢的區別是,我們限定了返回結果的欄位,我們只要name和age兩個欄位。

{n user(id: "9527") {n namen agen }n}n

這個簡單的例子可以看出我們的GraphQL可以方便的支持參數(其實還能支持的更好看,我們後面會講)。 那我們如果我們的客戶端需要更多的數據怎麼辦,可以方便的擴展。

{n user(id: "9527") {n namen agen emailn friends{n namen agen }n }n}n

這個查詢就體現出GraphQL的威力了,我們多要了兩個欄位email和friends。email沒啥好說的,就是一個單一的值,但friends可是實打實的對象集合。對於這種對象,或者說複雜類型,我們可以繼續給它指定需要的欄位,這裡我們指定了 name和age。

你還可以在friends里再指定friends來拿到朋友的朋友。你可以各種嵌套來達成你的查詢目的,數據也不在是單一的資源,而形成了一個圖。我就是看中這個特性才跳坑的,這種圖形化的查詢對現代前端和數據工程師都非常有用。我在不少地方都提到過,GraphQL不止可以給前端調用,它給後端以及數據和演算法工程師的代碼調用也是很好的。

當然,如此強大的查詢也讓很多後端程序員為GraphQL的性能擔心,可真的有問題嗎? 這得結合GraphQL的後端實現來給各位解答,首先GraphQL是很輕功能薄的一層,也就是說它自己額外產生的延遲(Overhead)是很低的。其實絕大多數人擔心的是,GraphQL會不會額外產生過多資料庫的查詢。我覺得這個擔心是有道理的,如果你給每一個欄位都上一個resolver函數,函數里直接執行資料庫查詢,那當然會產生非常多的查詢。可目前已有的GraphQL後端實現(包括JavaScript, Go,Java和Scala)給你提供了非常靈活的自定義優化方式。比如說你可以結合使用Cache和Context對象來減少資料庫查詢次數,具體如何做我以後結合具體的框架再來講。而且大家可以想像一下Facebook訪問量和界面複雜程度,據說這東西是讓他們更輕鬆了,為什麼我們不行?問題都是可以優化和解決的。關於後端的工作量,本篇最後會談。

那我們拿到的數據是什麼樣子的呢,這也是我最喜歡GraphQL的地方之一,調用方可以明確知道返回數據的結構,或者說裡面都有什麼,這是Rest API做不到的。我們來看上面那個GraphQL的返回。

{n data:{n user:{n name:"beinan」,n age:18,n email:"aaa@a.com」,n friends:[n {n name:"friend1」,n age:17n },n …..n ]n }n }n}n

這個返回結果完全適合你的請求同構的。那麼在前端,你有什麼樣的view, 需要什麼樣的數據,你就構建什麼樣的請求,得到的結果你就可以直接用來生成和填充你的view。再複雜的view你也可以一次查詢請求搞定,這對前端的反應速度和開發效率是個巨大的提升。後面章節(估計要很多節以後了)我會寫一個react的例子,來看看他們如何配合。

至於會不會增加後端工作量的問題,我看好多人問,我分幾點來討論,

1) 你一般不需要為GraphQL換語言,GraphQL各語言實現的進步非常快,基本都是易學易用,現在至少有十幾種主流語言支持GraphQL,基本常用的語言都支持了,這個速度是非常驚人的,一般的技術需要好多年才能覆蓋這麼多語言。

2) 你不需要為GraphQL換框架,GraphQL和框架無關,各種主流web框架,不管你是Django, Rails還是Express,哪怕是Spring MVC,Play Framework,Finatra都不矛盾。當然,你並不真的需要框架。

3) 如果你的服務是一個單一的大型Rest, 你可以把GraphQL 直接連接到你已有的Rest項目上(好處是你可以重用你已經實現的業務邏輯代碼,資料庫和Cache訪問代碼),這都是很容易,加一兩個endpoint(後面會講這一兩個是哪兩個)就行了。所以你可以讓GraphQL和你的Rest並行一段時間。

4) 如果你的服務已經很好的使用了微服務的構架,你也不需要重寫你的服務,你可用GraphQL擋在所有後端服務前面來自由拼裝你的微服務。

5) 關於優化,如果訪問量大,的確需要優化GraphQL對資料庫的訪問,任何後端服務在大訪問量面前都需要優化。不過我個人覺得GraphQL的優化相對容易做,畢竟是一個單一的訪問,都共享一個單一的context對象,你可以從全局出發進行優化,你可以做的事情更多。而Rest會產生多次請求(多次請求本身就是一個不小的問題),這些請求很可能分發到不同的伺服器,即便在同一個伺服器你也很難控制它們到達的先後順序。其實Rest的優化更難。

下回我們來講GraphQL如何定義數據,我寫的慢,請大家耐心等待。。。

推薦閱讀:

如何評價 Meteor 的替代品 Meatier?
API的過去,現在與未來

TAG:Web开发 | GraphQL | 网站架构 |