GraphQL實戰-第一篇-GraphQL介紹
https://blog.csdn.net/xplan5/article/details/108716321
GraphQL的前世今生
Facebook的業務線有移動端,PC端和其它端,不同的場景下對一個資源所需要的信息是不同的。如移動端需要User的a、b、c三個字段,PC端需要b、c、d三個字段;對於此場景,要么開多個定制化API接口,會造成代碼冗余,要么一個全信息API接口,有接口信息冗余。
造成了不止以下三個痛點
- 移動端需要高效的數據加載,被接口冗余字段拖累
- 多端產品下,API維護困難
- 前端新產品快速開發困難,需要大量的后端配合寫業務定制化API
解決以上問題,2012年Facebook在開發中形成了一套規范,就誕生了GraphQL,並於2016年將此規范開源。
API開發方式的發展,從SOAP到REST,經歷了很多年,GraphQL也許是下一代的API方式,發展的共同特點是,API越來越自由,越來越靈活。
GraphQL-API查詢語言
GraphQL是什么?
官方的解釋是 GraphQL是一種用於API的查詢語言。
怎么理解API查詢語言,我們知道SQL是結構化查詢語言,是查數據的,當然也能操作數據。同為Query Language 當然是有相同點的。
GraphQL和SQL
- SQL 是對數據庫(服務端)的操作語言
- GraphQL 是對API接口(服務端)的操作語言
數據庫分為服務端和客戶端,我們最為客戶端寫SQL來操作數據庫;
GraphQL也分服務端和客戶端,這里講的是服務端為主。客戶端就是接口調用方,暫且理解為前端;服務端就是提供接口的后端服務。
GraphQL可以簡單理解為,客戶端 操作 API, 后端業務系統作為數據庫為客戶端提供服務。
GraphQL的優點
現在來看看GraphQL做到了什么。
一 接收的數據不多不少
向你的API發送一個GraphQL請求 就能准確獲得你想要的數據,不 多不少。沒有任何數據冗余。這是graphql最大的優點,客戶端在GraphQL的請求腳本中指定查詢的字段,API就不會返回任何多余的字段。
對應於SQL就相當於:
SELECT age,name
FROM USER
WHERE id = 1532;
對應的GraphQL語句就是
{
queryUser(id:1532) {
age
name
}
}
下圖是使用效果:
這個特點,避免了網絡傳輸的數據冗余,對前端的性能有改善,對於后端的優化也提供了新的方向,如根據GraphQL的需求,動態生成對應的sql,避免每次查全數據庫字段帶來的性能損耗。
二 獲取多個資源,只用一個請求
簡單來說就是,多個接口的調用,可以放到一個http請求中來做,並且自定義數據返回的格式,包括指定變量名。
傳統的REST請求,是一次http請求,只操作一個API的內容,如一個場景下需要查詢用戶信息,商品信息和訂單信息。要么前端調三次接口,要么后端封裝一個定制的接口。
示例:
graphql多次調用服務獲取資源:
獲取用戶信息
query queryUserInfo {
getUserInfoByID(userId:1890) {
userName
userAge
mailbox
}
}
獲取商品信息
query queryProducts {
getProducts(device:web) {
productName
productid
sppu
price
}
}
獲取訂單信息
query queryOrders {
getOrdersByUserId(userId:1890) {
orderId
orderNo
}
}
以上內容,一次請求接口與搞定
query {
user: getUserInfoByID(userId:1890) {
userName
userAge
mailbox
}
products: getProducts(device:web) {
productName
productid
sppu
price
}
orders: getOrdersByUserId(userId:1890) {
orderId
orderNo
}
}
這個特點在移動端弱網環境下,也能高效的加載數據;而對於后端,也會相應減少Servlet線程是使用次數,可以有更高的系統吞吐量;另一個方向,一次請求多個接口,也可以采用異步執行,提升服務端的響應效率...
三 描述所有可能的類型系統
graphql的schema真正做到了代碼及文檔,服務端定義好graph后,客戶端可以方便的查看到結構模型,客戶端寫腳本的時候graph也會起到很好的輔助作用。
這一特點對於接口文檔有了重新定義,后端定義好graph,前后端就可以同時開發業務,之后前端在需要組合類的API業務,只需要在這些原子性的API中組合數據即可。
以上三點就是GraphQL的明顯優勢
四 方便的調試工具GraphiQL
GraphqiQL是一個用於調試graphql的開發工具,包括調試接口和文檔查詢,他有代碼提示和校驗的功能。在代碼集成插件后,可以在瀏覽器直接使用。
五 較低的遷移成本
很多人由於考慮到龐大的老系統,從REST遷移到GraphQL過程中有很高的遷移成本,導致放棄使用GrqphQL。
這一點是多慮了,第一,graphql和rest是可以兩種形式並存的,並不是說使用graphql后必須放棄之前的REST方式,其實有一部分的場景還是REST實現更方便;第二,只要選擇或者設計好graphql的實現方式,完全可以使用現有的業務代碼,可以很快開發出一套graphql的版本。
六 系統可以無感升級
對於API的升級,只要不是刪字段的情況,服務端的接口增加字段,增加API方法對於客戶端的使用是沒有任何影響的,既不會改變URI,也不會造成API升級帶來字段冗余的情況。
GraphQL與REST
GraphQL可以認為是REST的改良版。
graphql需要借助REST來暴露一個url地址,通過REST的形式更方便的操作定義的API。
一套系統中GraphQL與REST可以共存,並且很多場景下都是這樣的。通過設計也可以共用一套權限驗證的邏輯,業務代碼就更是能夠共用了。
一般情況下,REST是一個API對應一個URI.而GraphQL是可以所有的API共用一個URL,甚至客戶端可以根據業務自己組合一個業務上的API。
GraphQL的缺憾
GraphQL有很多優點,但GraphQL也不是完美的。也有一些缺憾的地方。
- GraphQL是Facebook發明的,並將GraphQL的規范開源。但Facebook的后端 設計並未開放,並且很難找到成功的示例。就連GraphQL的封裝實現是第三方做的。
- 並不是所有的API都適合GraphQL來做
- 前期沒有經過認真設計的GraphQL實現,容易造成一些性能問題
- 首次接觸GraphQL的開發者,一定會遇到一些不好解決的問題,如N+1的問題:查詢主信息附帶子信息的場景,處理不好的話容易造成先根據id查詢主表后獲取到子表ids,然后循環根據子表id查詢子表信息,這就造成了查詢n+1次數據庫,當然這個問題在REST中也是存在的,只不過GraphQL場景下解決起來似乎更加麻煩一點。權限驗證:通常的權限驗證是在網關層根據接口路徑做的校驗,如果是GraphQL的話只有一個URI資源,所以權限驗證的方案就得重新設計了...
對GraphQL的期望
選擇一個新的技術,一般是為了解決現有的痛點或者是使技術或方法體系能夠得到進一步的升級。
這里談一下筆者對GraphQL的一些期望
- 清晰的描述系統的功能:通過Graph的定義,使上游業務方可以清楚的了解我們開發的API結構,從而能夠達到自助調用接口的目的。
- 構建強大的開發者工具:GraphQL是一套規范,基於這套規范開發出一款自動化的工具,如根據GraphQL自動生成SQL調用數據庫,自動調用第三方系統,自動生成一些業務計算的邏輯,從而減少后端業務的開發量
GraphQL的執行
GrsaphQL並不是一套神秘的黑盒技術,這是它的優點,讓每一個真正使用的它的人先了解它的原理;這也是它的缺點,很多需要實現的功能都需要自己開發。
前邊說了GraphQL是一套規范,是一個查詢語言,自然就有它的使用規范和操作語法需要學習了。這邊簡單提一下,Schema中需要定義操作類型,對應的graphql需要定義一系列業務相關的Type,Input...
type Query {
human(id: ID!): Human
}
type Human {
name: String
appearsIn: [Episode]
starships: [Starship]
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Starship {
name: String
}
有關GraphQL的規范建議到官網上去學習了解:https://graphql.cn/learn/execution/
寫在最后的話
GraphQL是2012年產生,與2015年開源的一套規范,相應的各個語言都有第三方實現的一套簡單的框架。https://graphql.cn/code/
在國外的一些開發者者手中,陸續有一些自研的插件被開源,使用也很方便,在或許的分享中會有體現。當然,GraphQL在國內還沒有大面積使用,包括相關的技術分享也極其保守,很少有人分享自己對GraphQL的設計及問題處理。
很多人覺得,GraphQL出現到現在已經好多年了,現在還是沒有火起來,認為GraphQL已經沒戲了,如果去了解一下SOAP到REST的演化,或許就不這么想了。也有人認為,GraphQL只適合一些個新業務的小項目去練手,或者老系統中在REST的基礎上再維護一套GraphQL,認為GraphQL是上不了台面或扛不起任務的一個技術,筆者認為這個觀念有點悲觀,一個新技術的流行,是需要全方位的配合,一整套系統中,需要前端,后端,還需要各個產品線的配合,如果只是一個點的試驗,確實推行的阻力會很大。還有一些人是主推GraphQL的缺點,以至於一些人了解缺點之后立即放棄並大肆傳播,如一些文章標題就是《GraphQL從入門到放棄》《GraphQL使用它的五個理由和不使用的五個理由》...筆者認為,沒有完美的技術,我們需要做的是理性的看待新事物,並積極的接受新事物,對應新技術我們應該放大其優點,解決其短板。就像我們接受微服務的時候,並沒有因為微服務帶來的分布式事物等難題而放棄使用它。
CLC