2019-GraphQL-簡介
REST 與 GraphQL 比較
REST
表現層狀態轉換
英語:Representational State Transfer
REST是設計風格而不是標準
在2000年出現。
資源是由URI來指定。
使用HTTP協定提供的GET、POST、PUT和DELETE方法。
- 優點:
- 系統撰寫靈活。
- 風格統一,直觀簡潔的URL。
- api獨立不互相影響。
- 在瀏覽器輸入URL即可獲取資料。
- 目前主流風格。
- 缺點:
- 參數、回傳值型別不固定。
- 不容易處理巢狀資源。
- 一個URL只能獲取特定資源,結構鬆散問題導致多條件查詢得創造多個URL。
- 因為無狀態,每一次只能傳輸一筆資料,無法有效的整合所需資料一次性取得。
- 會拿多餘的欄位,一次回傳的資料都為完整的結構,無法取捨不需要的資料,以至於傳輸量的增加。
- 不斷成長的 Endpoint 數量。
GraphQL
GraphQL 是一種為 API 設計的資料查詢(修改)的語言
由Facebook及社區開發。
在2012年出現在2015公開釋出。
大概念上有點類似 SQL。
GraphQL 服務是通過定義類型和類型上的字段來創建的,
然後給每個類型上的每個字段提供解析函數。
-
出現原因:
- 資料傳遞速度嚴重影響效能。
- 不同平台所需的資料數量、格式都不同。
- 前後端溝通難度增加。
- Legacy API 難以處理。
- 結構鬆散與查詢分割過多,導致URL過多。
-
優點:
- 精準資料取得。
- 資料只拿剛好且彈性十足。
- 前後端溝通成本減少。
- 程式即文檔。
- 前端控制權提升。
- 高度自由的實作方式。
- 不預設綁任何程式語言 (language agnostic) 或是資料庫 (DB agnostic)。
- 可將不同 micro service 的 GraphQL schema 串接在一起。
- 強型別,型別錯就直接被擋下來。
- 支援五種基礎型別 (Scalar Types)。
- 能自定義型別。
-
缺點:
- 沒有一定的實作規範,可能因為前後端對於架構的疏忽或不了解導致設計出過於複雜的 Schema。
- 仍是一種新技術(?)相關社群仍在開發中。
- 很容易一不小心陷入 RESTful API 的設計思維、埋下更多技術債。
- Server Side Caching 實作困難。
簡易介紹
簡單來說:
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
設計:
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
有了 GraphQL
可以把商業模型 (business model) 像圖形 (graph) 一樣串連起來。
Query 是 Client side 是符合 schema 規定的查詢語言格式。
Schema 是 Server side 定義整體資料結構格式。
資料架構(Schema)
Schema 大概結構圖
快速簡介
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
大致分別
-
型別 (type)
-
遞迴 (recursive) 取值
- 展開並選取需要的資料。
- query 結構最末端的 field 一定要是 Scalar Type。
範例
宣告時的結構:
schema的整合
Query的功能表
回傳的Object
在LogInToken Object 中的 Object
實際請求:
實際回傳:
主要Schema
介紹
每一個 GraphQL 服務都有一個 query 類型。
可能有一個 mutation 類型。
這兩個類型和常規對像類型無差,但是它們之所以特殊,是因為它們定義了每一個 GraphQL 查詢的『入口』。
可明確分別功能所使用的schema。
範例
查詢結構
介紹
一個 GraphQL schema 中的最基本的組件是對像類型,它就表示你可以從服務上獲取到什麼類型的對象,以及這個對像有什麼字段。
並且有以下功能:
範例
備註
如果這個參數上傳遞了一個空值(不管通過 GraphQL 字符串還是變量),那麼會導致服務器返回一個驗證錯誤。
範例
myField: [String!]
myField: [String]!
資料結構
介紹
GraphQL 自帶一組默認標量類型(Scalar type)
- Int:有符號 32 位整數。
- Float:有符號雙精度浮點值。
- String:UTF‐8 字符序列。
- Boolean:true 或者 false。
- ID:ID 標量類型表示一個唯一標識符,通常用以重新獲取對像或者作為緩存中的鍵。ID 類型使用和 String 一樣的方式序列化;然而將其定義為 ID 意味著並不需要人類可讀型。
GraphQL 也可使用自定義組合類型(Object type)
這種『自定義且』、『能展開』的類型稱為Object type。
備註
大部分的 GraphQL 服務實現中,都有『自定義標量類型』的方式。
例如,我們可以定義一個 Date 類型:
然後就取決於我們的實現中。
例如,你可以指定 Date 類型應該總是被序列化成整型時間戳,而客戶端應該知道去要求任何 date 字段都是這個格式。
範例
類型
枚舉類型
枚舉類型是一種『特殊的標量』
它『限制』在一個特殊的『可選值集合』內。
驗證這個類型的任何參數是可選值的的某一個,
一個字段總是一個有限值集合的其中一個值。
下面是一個用 GraphQL schema 語言表示的 enum 定義:
這表示無論我們在 schema 的哪處使用了 Episode
都可以肯定它返回的是 NEWHOPE、EMPIRE 和 JEDI 之一。
接口類型
一個接口是一個抽像類型,它包含某些字段
而對像類型必須包含這些字段,才能算實現了這個接口。
這意味著任何實現 Character 的類型都要具有這些字段,並有對應參數和返回類型。
聯合類型
聯合類型和接口十分相似,但是它並不指定類型之間的任何共同字段。
任何返回一個 SearchResult 類型的地方,都可能得到一個 Human、Droid 或者 Starship。
注意,聯合類型的成員需要是具體對像類型;你不能使用接口或者其他聯合類型來創造一個聯合類型。
範例
輸入類型
我們只討論過將例如『枚舉』和『字符串等標量值』作為參數傳遞給字段
但是你也能很容易地傳遞複雜對象。
在 GraphQL schema language 中
輸入對像看上去和常規對像一模一樣,除了關鍵字是 input 而不是 type
開發模式
1. REST + GraphQL Hybrid
如果直接建立一個新的GraphQL,會造成前端維護的困難,因為要同時處理 REST 與 GraphQL 的結構。
透過虛擬轉換的方式間接導入 GraphQL。
利用擴充的方式,將RESTful的部分抽象出來,加以設計。
引用圖片

2. GraphQL Layer
把 GraphQL Server 抽出來放到中間當作 GraphQL Layer。
既可以處裡API引用也可以直接處理DB。
引用圖片

3. GraphQL API Gateway
GraphQL Gateway 不直接與 Database 溝通,
而是把前端的 Requests 需求往後面的 API Service 送。
而後面直接與 Database 串接的 GraphQL Server 稱為 GraphQL Native。
引用圖片

Demo
使用Framework:99designs/gqlgen
套件Github:https://github.com/99designs/gqlgen
文檔:https://gqlgen.com/
開發時間: 11 天 (2019/1/15 ~ 2019/1/17)
PS.包含新的DB引用、新結構的重構(完全不使用公司內的任何套件),寫資料等。
可使用數量: 2 個
可使用功能:Optend、Generalreport
目前架構
起動流程
系統流程
請求格式
URL
- Accept-Encoding
- Content-Type
- Accept
Body
Optend
一般
結構
傳送內容
測試結果
錯誤
結構
傳送內容
測試結果
Generalreport
一般
結構
傳送內容
測試結果
{
"data": {
"Generalreport": [
{
"ChannelName": "VG-棋牌",
"ChannelCode": "vg_qipai",
"WalletCode": "vg",
"Others": "",
"Items": [
{
"name": "backendaa",
"level": "1",
"ordercount": "32",
"total": "194",
"earning": "161.55",
"point": "230.05",
"prize": "0"
},
{
"name": "ccp88888",
"level": "1",
"ordercount": "158",
"total": "246276.99",
"earning": "12964.84",
"point": "245756.39",
"prize": "0"
},
{
"name": "test11111",
"level": "1",
"ordercount": "76",
"total": "3790.18",
"earning": "809.86",
"point": "3773.42",
"prize": "0"
}
],
"Pager": {
"Index": "",
"Pages": "",
"Size": "",
"Total": "3",
"TotalOrderCount": "266",
"Amount": "250261.17"
}
},
{
"ChannelName": "福彩/体彩",
"ChannelCode": "fctc",
"WalletCode": "cp",
"Others": "",
"Items": [
{
"name": "backendaa",
"level": "1",
"ordercount": "3",
"total": "12",
"earning": "12",
"point": "12",
"prize": "0"
},
{
"name": "ccp88888",
"level": "1",
"ordercount": "30",
"total": "13170",
"earning": "13160.15",
"point": "13170",
"prize": "0"
}
],
"Pager": {
"Index": "",
"Pages": "",
"Size": "",
"Total": "2",
"TotalOrderCount": "33",
"Amount": "13182"
}
},....
Golang Framework Comparison
時間:
Framework version |
Time |
playlyfe/go-graphql |
2018-12-03T01:16:34Z |
graph-gophers/graphql-go |
2017-04-28T20:40:03Z |
samsarahq/thunder |
2018-11-28T22:09:52Z |
99designs/gqlgen |
2018-12-02T22:03:39Z |
Summary
|
Requests/sec |
graphql-go |
33448.20 |
graph-gophers |
72506.58 |
thunder |
71551.64 |
gqlgen |
99645.21 |
Without graphql (only gin render json output)
|
Requests/sec |
json without graphql |
124663.94 |
其他
使用公司:https://graphql.org/users/
參考
- https://ithelp.ithome.com.tw/articles/10200678
- https://ithelp.ithome.com.tw/articles/10188294
- https://medium.com/@evenchange4/2018-graphql-漸進式導入的架構-aeb2603f2223
- http://graphql.cn/
- http://graphql.org/