graphql 是一種用于 API 的查詢語言,對你的 API 中的資料提供了一套易于了解的完整描述,使得用戶端能夠準确地獲得它需要的資料,減少資料的備援。
聲明類型
type Project { name: String
tagline: String
contributors: [User]
}
查詢語句
{ project(name: "GraphQL") {
tagline
擷取結果
{ "project": {
"tagline": "A query language for APIs"
簡單了解
資料結構是以一種圖的形式組織的

圖結構的資料
與 RESTful 不同,每一個的 GraphQL 服務其實對外隻提供了一個用于調用内部接口的endpoint,所有的請求都通路這個暴露出來的唯一端點。
GraphQL 實際上将多個 HTTP 請求聚合成了一個請求,它隻是将多個 RESTful 請求的資源變成了一個從根資源 <code>Post</code> 通路其他資源的 <code>school</code> 和 <code>teacher</code>等資源的圖,多個請求變成了一個請求的不同字段,從原有的分散式請求變成了集中式的請求。
可互動的查詢 用戶端請求字段,伺服器根據字段傳回,哪怕是數組類的結構依然可以根據字段名自由定制
使用參數查詢
使用别名
有的時候希望在一次請求過程中,對同一個字段使用不同的參數做兩次請求
片段(Fragments)
片段使你能夠組織一組字段,然後在需要它們的的地方引入,達到複用單元的意義。
變量
用戶端不需要每次拼接一個類似的query,通過送出不同的變量來實作
内聯資料塊
如果查詢的字段傳回的是接口或者聯合類型,那麼你可能需要使用内聯片段來取出下層具體類型的資料:
變更(Mutations)
不隻是查詢,還能夠變更資料
example:
schema 檔案入口
query 操作聲明
枚舉類型
對象類型和字段
參數
接口類型
輸入類型
實作特殊的接口的對象類型
基于接口類型的查找類型
使用interface 類型 進行查找
從更大的角度來看,GraphQL API 的主要應用場景是 API 網關,在用戶端和服務之間提供了一個抽象層。
image
擁有包括移動端在内的多個用戶端;
采用了微服務架構,同時希望有效管理各個服務的請求接口(中心化管理);
遺留 REST API 數量暴增,變得十分複雜;
希望消除多個用戶端團隊對 API 團隊的依賴;
如果說grpc 面向過程的抽象,rest 面向的是資源的抽象,那麼graphql 則是面向資料的抽象。是以graphql 更适合的場景是互動方更貼近資料的場景。
中台資料的一些挑戰和grapqhl能夠提供的優勢:
豐富而異構的資料點以及挑戰,對資料點的開發添加有效率上的要求
graphql 在接口設計上據有很好的可擴充性,新加的資料點不需要新添加接口endpoint,隻需要添加适合的字段名。對現有的接口影響也很小。
多元度的資料模型的聚合,高度的複雜度,和服務更高耦合的接口,複雜度提升造成接口管理的困難。
多元度的資料更容易使用圖的結構描述,并且可以屏蔽各個服務調用細節,使用中心化的schema 管理資料,可以更靠近字段而非以接口為管理的單元。
對應不同需求的使用者調用
B端/C端 使用者調用需求個有不同,graphql 統一了調用方式,不需要為不同的目的定義不同的接口調用。如果各B 端使用者對接口調用的方式有需求,隻需要在graphql 服務之前做一次接口轉換就可以,對現有系統侵入很少。
GET 請求
url: http://myapi/graphql?query={me{name}}&var.name=
POST 請求
{
"query": "{me{name}}",
"operationName": "...",
"variables": { "myVariable": ""}
響應
無論使用任何方法發送查詢和變量,響應都應當以 JSON 格式在請求正文中傳回。如規範中所述,查詢結果可能會是一些資料和一些錯誤,并且應當用以下形式的 JSON 對象傳回:
"data": { ... },
"errors": [ ... ]
golang github.com/graphql-go/graphql
graphql 作為的網關特點,在一次請求中可能會通路多個服務,在沒有優化的情況下,往往會發送多個請求給背景服務。造成性能浪費
解決方案 DataLoader
DataLoader被廣泛地應用于解決[N+1查詢問題]
對于多個相同類别的資料使用同一個請求,傳入多個id 傳回多個資料。
image.png
緩存
記憶體級别的緩存,load一次,DataLoader就會把資料緩存在記憶體,下一次再load時,就不會再去通路背景。
可以自定義緩存政策等
Rejoiner Generates a unified GraphQL schema from gRPC microservices and other Protobuf sources
多版本調用
Schema 的管理去中心化,由各個微服務對外直接提供 GraphQL 請求接口,graphql service通過請求的字段名陸遊到各個服務 同時将多個服務的 Schema 進行合并
粘合schema
優點:
schema 粘合,以此來解決開發的效率問題。對于新的資料子產品(粗粒度的服務),隻需要提供最新的子產品的schema,解決相同類型資料的沖突,graphql service 就能夠自動提供merged 之後的schema。
缺點:
每個微服務需要提供graph 接口,對接schema,使得微服務耦合了graphql 接口。
同名的類型需要解決沖突,但是解決沖突的方案可能包含業務邏輯,靈活性不是最高
粘合的功能可能還需要承載服務發現以及流量路由等功能,複雜度高,穩定性要求高
目前比較成熟的Schema Stitching方案隻有基于nodejs 的,社群還不完善。
但是隻找到了 javascript 解決方案
中心化調用
一個中心化的schema和graphql service,各個微服務提供rpc 接口或者rest api接口,graphql service主動調用别的微服務rpc 接口,按照schema進行組合最後傳回給前端。
graphql service主動組合各個服務
對于子系統沒有侵入,各個微服務和graphql 沒有耦合。
graphql作為網關服務有更強的控制粒度,更加靈活,更加容易附加業務邏輯(驗證,授權等)。
接口聚集之後,如果接口頻繁改動,對與graphql service 開發壓力更大,流程上都依賴于graph 網關服務。
對于後端資料服務的職責劃分要求更高。不宜把過重的業務邏輯放置到graphql service 中
缺失的版圖:
由于graphql是面向資料的接口,是以架構上面必然需要有能力去描述這種圖的資料模型。這樣更接近本質。個人覺得目前生态中缺少一個面向資料圖的服務級别的粘合器,可以中心化配置,靈活調用各種局部解析器,将整個微服務叢集,從資料的角度組織成一張網絡(graph)。
graph technical.png
使用複合模式,綜合多schema / 單schema 的優點:
可以通過代碼或者擴充組建定制化,同時使用一些類schema (grpc protocl)代碼自動生成graph schema,結合二者的資料結構。
可以中心化配置,整體對于graph 有統一的對外結構。
微服務叢集需要與graphql解耦:
graphql service 不應該和微服務有過高的耦合,一些服務中間建的功能應該從graphql service移除,例如服務發現和負載均衡,流量控制等。
3人點贊