天天看點

graphql 介紹

graphql 是一種用于 API 的查詢語言,對你的 API 中的資料提供了一套易于了解的完整描述,使得用戶端能夠準确地獲得它需要的資料,減少資料的備援。

聲明類型

type Project { name: String

tagline: String

contributors: [User]

}

查詢語句

{ project(name: "GraphQL") {

tagline

擷取結果

{ "project": {

"tagline": "A query language for APIs"

簡單了解

資料結構是以一種圖的形式組織的

graphql 介紹

圖結構的資料

與 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}}&amp;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人點贊