接口是行爲的定義,肯定了跟系統交互的界面。 行爲的實體是函數,函數包括定義和實現,而接口只關注函數的定義。 函數定義包括傳人蔘數和返回值,包含了參數名稱和類型,包含了返回值的類型。後端
GraphQL是接口網絡
GraphQL本質上是一種接口的定義規範,裏面包括了種類型定義和函數定義(名稱,參數,返回值),能夠精確的定義了先後端交互的界面。函數
GraphQL不是通常的接口 工具
GraphQL是隻定義接口,不關心實現,自己是語言不相關的。開發工具
這意味着GraphQL能夠做爲鏈接不一樣系統的統一規範。spa
GraphQL包含嚴格的類型定義,這種定義能夠用來進行代碼生成,結合自己有提供不少輔助開發工具,能夠輔助解決接口的定義、實現、文檔、調試問題。設計
以上所說的這些,不少rpc平臺,像grpc、thrift都能解決。着這個角度講,GraphQL就是一種rpc協議。調試
若是要說不一樣之處,GraphQL設計之處的目的是解決先後端交互的問題。先後端交互網絡傳輸是一個問題。code
傳統的rpc返回結果的時候回返回完整的數據,可是不少時候咱們只須要結果中的部分數據,這樣傳輸無用數據會形成帶寬浪費,同時也會影響處理速度,對於響應要求高或者網絡帶寬不夠的應用不利,移動應用就屬於這類。cdn
使用GraphQL接口時,能夠基於定義約定想要的東西,而後GraphQL會根據請求,只返回想要的數據,這點相似於SQL。同時,能夠在一次GraphQL請求發送多個函數調用請求,這樣能夠減小請求的發送量,從而提升響應速度。
舉例說明
下面咱們用Go語言定義了一個簡單的類型和接口。
// 定義的User類型
type User struct {
ID int
Name string
Age int
Posts []Post
}
type Post struct {
ID int
Title string
Owner User
}
// 定義的查詢接口
type Query interface {
FetchUsers() []User
FetchPosts(userID int) []Post
GetUserById(id int) *User // 定義了函數的參數和返回值
}
// 定義的修改接口
type Mutation interface {
CreateUser(name string, age int) User
DeleteUser(id int) *User
}
複製代碼
咱們知道,接口若是成功調用,會返回一個完整的數據。好比,GetUserById成功調用後會返回一個完整的User給咱們。 這裏包括大量User的所有屬性, 形如User {ID: 0, Name: "Alex", Age: 28}。 可是若是咱們帶寬太窄,只須要User的Name信息呢? 這裏就是graphql跟接口不一樣的地方。像SQL同樣,使用GraphQL你能夠聲明你須要什麼屬性。
{
GetUserById(id: 1) {
Name
}
}
複製代碼
接口,你調用一個函數,返回一個結果。你返回多種結果,調用屢次函數。 使用GraphQL,你可以把多個對數據的要求放在一個請求裏面。
{
GetUserById(id: 1) {
Name
}
FetchPosts(userId: 1) {
title
}
}
複製代碼
並且,GraphQL還支持順着類型定義嵌套的抓取信息。 上面的查詢也能夠寫成下面的形式。
{
GetUserById(id: 1) {
Posts {
title
}
}
}
複製代碼
固然你也能夠喪心病狂的不斷嵌套抓取數據。
{
GetUserById(id: 1) {
Posts {
title
Owner {
Name {
Posts {
title
...
}
}
}
}
}
}
複製代碼
這種按照接口的類型定義,不斷嵌套的抓取數據正是GraphQL中Graph的由來,表達了Graph + QL = 按圖 + 索驥內涵。 固然這種變態的抓取是很是恐怖的,若是有壞人故意發這種請求搞死咱們,咱們就完了,因此必須有一種方式來限制這種行爲。 好在,咱們能夠對用戶的請求進行AST語法分析,限制嵌套的深度,好比,咱們可讓你最多嵌套3層。
總結
GraphQL本質上是一種爲了解決先後端交互問題二設計的接口協議。很好的解決了接口的定義、文檔、調試、使用等問題,目測會愈來愈火。