restQL is a microservice query language that makes easy to fetch information from multiple services in the most efficient manner. http://restql.b2w.io/
介 紹
restQL的設計是用來簡化客戶端查詢,特別是在微服務時代,對於一個複雜的頁面,可能需要調用多個服務的接口,獲得數據渲染頁面。這對於客戶端來說,這有著極大的消耗。而 restQL較好的解決的這個問題,並且使用restQL對原來API server無需改動。
restQL支持以下幾種查詢方式。
並行調用(Parallel calls)
他們所產生的查詢,是併發進行的,等待所有的處理完成後將直接返回。
from hero
with
name = "Restman"
from villain
with
name = "SOAPLord"
鏈式調用(Chained invocations)
第二個查詢依賴第一個查詢的結果,所以需要等待第一個查詢結束後,才會調用第二個查詢,最終返回結果。
from hero
with
name = "Restman"
from sidekick
with
hero = hero.id
Multiplexed invocations
這個同樣是第一個查詢依賴第二個查詢,但是第一個查詢出來的是一個array,並對於array中的每個元素,調用第二個查詢,處理完成後返回。
from search
with
role = "hero"
from hero as heroes
with
name = search.results.name
詳細介紹見:http://restql.b2w.io/
安 裝
restQL依賴一個restQL-http對外提供服務,由restQL-http解析restQL的查詢語言並且調用資源服務(API server)
下載restQL-http到任意目錄,並且解壓,這裡安裝的是:
## 下載
curl -O https://github.com/B2W-BIT/restQL-http/releases/download/v3.5.5/restql-http-v3.5.5.zip
## 解壓
unzip -d restql-http restql-http-v3.5.4.zip
## 運行
cd restql-http
planets=https://swapi.co/api/planets/:id ./bin/run.sh
入 門
對於入門最好的方式,莫過於官方文檔了(http://docs.restql.b2w.io/#/restql/getting-started)。
官網是以swapi.co的API作為測試,這裡也將使用這個服務作為簡單的入門使用。如果需要配置更高級的使用方式(http://docs.restql.b2w.io/#/restql/config)。
運行
cd restql-http
planets=https://swapi.co/api/planets/:id ./bin/run.sh
啟動成功後,將會默認監聽9000端口,http://localhost:9000,也可以通過設置環境變量的方式,使其端口改變。
export PORT=1456
planets=https://swapi.co/api/planets/:id ./bin/run.sh
restQL提供的接口路徑是 :http://localhost:9000/run-query
可以通過curl方式調用服務,檢查是否啟動正常
curl -d "from planets as allPlanets" -H "Content-Type: text/plain" localhost:9000/run-query
正常情況下將會得到類似以下的輸出
{
"allPlanets": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": ...
}
}
查詢一條數據
restQL 查詢語句
from planets
with id = 1
調用接口,這裡推薦使用Postman、Insomnia等工具測試
curl -d "from planets with id = 1" -H "Content-Type: text/plain" localhost:9000/run-query
將會得到以下數據
{
"planets": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": {
"surface_water": "1",
"climate": "arid",
"residents": [
...
],
"orbital_period": "304",
"name": "Tatooine",
"diameter": "10465",
"created": "2014-12-09T13:50:49.641000Z",
"gravity": "1 standard",
"edited": "2014-12-21T20:48:04.175778Z",
"films": [
...
],
"population": "200000",
"terrain": "desert",
"url": "https://swapi.co/api/planets/1/",
"rotation_period": "23"
}
}
}
查詢語言
語法
查詢語句的順序,對於 restQL 異常的重要
[ [ use modifier = value ] ]
METHOD resource-name [as some-alias] [in some-resource]
[ headers HEADERS ]
[ timeout INTEGER_VALUE ]
[ with WITH_CLAUSES ]
[ [only FILTERS] OR [hidden] ]
[ [ignore-errors] ]
Methods
restQL 提供了HTTP常用的幾個 methods (GET,POST,PUT, PATCH, DELETE)
- from - HTTP GET
- to - HTTP POST
- into - HTTP PUT
- update - HTTP PATCH
- delete - HTTP DELETE
from
planets = https://swapi.co/api/planets/:id
restQL 語句
from planets
with
name = "Restman"
id = 1
將會映射到以下調用
GET https://swapi.co/api/planets/1?name=Restman
to
planets = https://swapi.co/api/planets
restQL 語句
to planets
with
name = "Restman"
將會映射到以下調用
POST https://swapi.co/api/planets
BODY {"name": "Restman"}
into
planets = https://swapi.co/api/planets/:id
restQL 語句
into planets
with
id = 1
name = "xxxx"
將會映射到以下調用
PUT https://swapi.co/api/planets/1
BODY {"name": "xxxx"}
update
planets = https://swapi.co/api/planets/:id
restQL 語句
update planets
with
id = 1
name = "abc"
將會映射到以下調用
PATCH https://swapi.co/api/planets/1
BODY {"name": "abc"}
delete
planets = https://swapi.co/api/planets/:id
restQL 語句
delete planets
with
id = 1
將會映射到以下調用
DELETE https://swapi.co/api/planets/1?name=Restman
實 踐
這裡將以 https://api.spacexdata.com/ 作為數據服務,接下來的所有數據,都是由它來提供。(https://docs.spacexdata.com/?version=latest)
restQL 支持多種資源映射方式,可以通過環境變量,也可以通過restql.yml的方式亦或者通過restQL-manager(http://docs.restql.b2w.io/#/restql/manager)前面演示了通過環境變量的方式,這裡將通過restql.yml,在restql-http目錄創建restql.yml文件。
restql.yml
mappings:
launches: "https://api.spacexdata.com/v3/launches"
執行
./bin/run.sh
啟動成功後,將可以看到類似這樣的輸出
2019-11-08 14:46:03,239 INFO restql.http.plugin.core [main] No plugins to load
2019-11-08 14:46:03,244 INFO restql.http.server.core [main] Server starting with {:port 1456, :executor-utilization 0.5, :executor-max-threads 512, :executor-control-period 1000}
2019-11-08 14:46:03,465 INFO restql.http.server.core [main] Server started!
簡單查詢
restql 語句
from launches
查詢結果
{
"launches": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": [...]
}
}
如果想要查詢 2017-06-22 到 2017-06-25 之間的數據,只需要給查詢語句加上 with
from launches
with
start = "2017-06-22"
end = "2017-06-25"
其他參數也按照這種方式。如果需要指定的獲取某一條數據,調用的接口是
https://api.spacexdata.com/v3/launches/{{flight_number}}
可以添加一條資源映射規則寫入到restql.yml,
mappings:
launches: "https://api.spacexdata.com/v3/launches"
oneLaunches: "https://api.spacexdata.com/v3/launches/:flight_number"
例如查詢的是 42
from oneLaunches
with
flight_number = 42
響應結果
{
"oneLaunches": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": {
...
"flight_number": 42,
...
}
}
}
過濾器(Filter)
restQL還支持一個filter特性,可以指定某個資源獲取的數據,這樣可以減少payload大小,對於移動客戶端優化非常重要。
這裡以 launches 作為演示。
from launches
with
start = "2017-06-22"
end = "2017-06-25"
only
mission_name,
flight_number,
launch_site.site_id,
ships,
rocket.first_stage.cores.land_success
響應結果
{
"launches": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": [
{
"mission_name": "BulgariaSat-1",
"flight_number": 42,
"launch_site": {
"site_id": "ksc_lc_39a"
},
"ships": [
"ELSBETH3",
"GOQUEST",
"GOSEARCHER",
"OCISLY"
],
"rocket": {
"first_stage": {
"cores": [
{
"land_success": true
}
]
}
}
}
]
}
}
並行查詢
並行調用,正是restQL需要處理的問題,能夠有效減少客戶端和服務器的連接數,對於微服務架構而言,可能一個頁面所呈現需要的數個服務來提供。這就意味著需要創建數個連接獲取資源,這對於客戶端來講,是非常糟糕的。
這裡添加一個新的資源映射地址,作為一個測試
mappings:
launches: "https://api.spacexdata.com/v3/launches"
oneLaunches: "https://api.spacexdata.com/v3/launches/:flight_number"
oneHistory: "https://api.spacexdata.com/v3/history/:id"
from launches
with
start = "2017-06-22"
end = "2017-06-25"
only
mission_name,
flight_number,
launch_site.site_id,
ships,
rocket.first_stage.cores.land_success
from oneHistory
with
id = 1
{
"launches": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": [...]
},
"oneHistory": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": {
"event_date_unix": 1222643700,
"title": "Falcon 1 Makes History",
"details": "Falcon 1 becomes the first privately developed liquid fuel rocket to reach Earth orbit.",
"id": 1,
"event_date_utc": "2008-09-28T23:15:00Z",
"flight_number": 4,
"links": {
"wikipedia": "https://en.wikipedia.org/wiki/Falcon_1",
"article": "http://www.spacex.com/news/2013/02/11/flight-4-launch-update-0",
"reddit": null
}
}
}
}
鏈式查詢
鏈式調用也是restQL的一個亮點,也簡單做一下演示
from oneHistory
with
id = 1
from oneLaunches
with
flight_number = oneHistory.flight_number
only
mission_name,
flight_number,
launch_site.site_id,
rocket.first_stage.cores.land_success
響應結果
{
"oneHistory": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": {
...
"flight_number": 4,
...
}
},
"oneLaunches": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": {
"mission_name": "RatSat",
"flight_number": 4,
"launch_site": {
"site_id": "kwajalein_atoll"
},
"rocket": {
"first_stage": {
"cores": [
{}
]
}
}
}
}
}
這個的應用場景也是極為廣泛的,特別在於頁面信息極其複雜的情況下,在一次請求就可以獲取到關聯的數據。
多路調用
為了避免歧義,這裡將添加一個新的映射地址,作為本次演示,編輯 restql.yaml文件
mappings:
launches: "https://api.spacexdata.com/v3/launches"
oneLaunches: "https://api.spacexdata.com/v3/launches/:flight_number"
history: "https://api.spacexdata.com/v3/history"
oneHistory: "https://api.spacexdata.com/v3/history/:id"
from history
with
start = "2016-06-22"
end = "2017-06-25"
only
flight_number
from oneLaunches
with
flight_number = history.flight_number
only
mission_name,
flight_number,
響應結果
{
"history": {
"details": {
"success": true,
"status": 200,
"metadata": {}
},
"result": [
{
"flight_number": 38
},
{
"flight_number": 41
}
]
},
"oneLaunches": {
"details": [
{
"success": true,
"status": 200,
"metadata": {}
},
{
"success": true,
"status": 200,
"metadata": {}
}
],
"result": [
{
"mission_name": "SES-10",
"flight_number": 38
},
{
"mission_name": "CRS-11",
"flight_number": 41
}
]
}
}
完 結
restQL 還有幾個高級特性,詳情請見官網
- http://docs.restql.b2w.io/#/restql/manager
- http://docs.restql.b2w.io/#/restql/saved-queries
- http://docs.restql.b2w.io/#/restql/plugins
參考鏈接
- http://restql.b2w.io/
- https://medium.com/b2w-engineering/restql-tackling-microservice-query-complexity-27def5d09b40
- https://github.com/B2W-BIT/restQL-http
原文鏈接:https://mp.weixin.qq.com/s/4fF19jc4Dgs92Q67MwN-Lw
關於睿雲智合
深圳睿雲智合科技有限公司成立於2012年,總部位於深圳,並分別在成都、深圳設立了研發中心,北京、上海設立了分支機構,核心骨幹人員全部為來自金融、科技行業知名企業資深業務專家、技術專家。早期專注於為中國金融保險等大型企業提供創新技術、電子商務、CRM等領域專業諮詢服務。
自2016年始,在率先將容器技術引進到中國保險行業客戶後,公司組建了專業的容器技術產品研發和實施服務團隊,旨在幫助中國金融行業客戶將容器創新技術應用於企業信息技術支持業務發展的基礎能力改善與提升,成為中國金融保險行業容器技術服務領導品牌。
此外,憑藉多年來在呼叫中心領域的業務經驗與技術積累,睿雲智合率先在業界推出基於開源軟交換平臺FreeSwitch的微服務架構多媒體數字化業務平臺,將語音、視頻、webchat、微信、微博等多種客戶接觸渠道集成,實現客戶統一接入、精準識別、智能路由的CRM策略,並以容器化治理來支持平臺的全應用生命週期管理,顯著提升了數字化業務處理的靈活、高效、彈性、穩定等特性,為幫助傳統企業向“以客戶為中心”的數字化業務轉型提供完美的一站式整體解決方案。
閱讀更多 睿雲智合Wise2C 的文章