在構建面向企業項目、多端的內容聚合類在線服務API設計的過程當中,因爲其定製特色,採用常規的restful開發模式,一般會致使大量雷同API重複開發的窘境,本文介紹一種GraphQL查詢語言+網關編排聯合的實踐,解決大量重複定製的問題。數據庫
早期與車廠合做過程當中,基於高德已有的數據、引擎能力和一些較爲重要的相關CP服務(如停車場、加油站、天氣等),造成的在線服務協做模式是針對客戶需求,採用REST API提供針對每一個車廠、每一個項目以及每一個終端提供不一樣的API實現,然而數據核心獨立服務實際上就有十餘種,然而因爲車線業務維護週期長,定製多,2-3年下來,API規模已達幾百個,並且持續發散級增加,這給持續開發和維護帶來不小挑戰。緩存
分解業務開發過程,無非兩類工做,業務需求能力數據的獲取和非業務訴求可是必不可少的如鑑權等通用化能力,當前來看,其實這兩個問題是幾乎全部業務團隊都會遇到的問題,所以解決方案也基本相似,如服務聚合、流程編排、API網關等。服務器
本文簡要介紹下車聯網在線服務改造舊架構的一些實踐。restful
GraphQL:GraphQL既是一種用於API的查詢語言也是一個知足數據查詢的運行時。GraphQL對API中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓API更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。架構
DSL:指的是專一於某個應用程序領域的計算機語言。又譯做領域專用語言。不一樣於普通的跨領域通用計算機語言(GPL),領域特定語言只用在某些特定的領域。 好比用來顯示網頁的HTML,以及Emacs所使用的Emac LISP語言。負載均衡
API網關:API網關是一個服務器,是系統的惟一入口。從面向對象設計的角度看,它與外觀模式相似。API網關封裝了系統內部架構,爲每一個客戶端提供一個定製的API。它可能還具備其它職責,如身份驗證、監控、負載均衡、緩存、請求分片與管理、靜態響應處理。函數
車線業務在線服務舊架構以下:工具
面臨如下問題:插件
針對上述問題,主要從如下幾個方面思考改進:設計
服務能力原子化:目標是作穩,讓上層經過組合實現業務需求;
構建查詢引擎:支持強大的查詢組合能力,實現原子服務能力任意聚合和定製;
API網關:對非業務數據能力需求進行抽象提供插件,實現插件編排。
下面分別介紹。
實現穩定、獨立演進的原子能力服務
對已有的服務進行梳理,抽象出不一樣應該獨立開發、部署演進的核心能力,對於引擎能力沒有什麼工做,重點是對於一些歷史對接的外部CP,主要實現如下目標:
向上提供穩定接口,向下屏蔽底層複雜性(數據訪問,多源差別);
以位置爲中心有機整合,構建完備原子化能力集合。
這部分工做主要是解決歷史遺留的一些服務組合不合理,跟隨業務過分定製的問題。
定製代碼開發轉換爲定義查詢語句
這裏主要目的就是將服務聚合、定製邏輯等原來須要的代碼開發轉換爲編寫查詢語言的方式實現,只須要編寫出聲明式的查詢語句即完成服務發佈,特性以下:
向上提供標準化查詢語言
向下實現原子能力組合
概括業務共性,提煉定製模式,提高複用
本文選擇GraphQL做爲查詢語言基礎,然而,直接採用GraphQL有這樣兩個主要問題須要解決:
數據查詢N+1放大問題,直接採用Fackbook提出的dataloader來解決,原理是批量加緩存;
GraphQL規範限制,一些定製難以實現,如:
入參定製:如參數關聯,類型轉換等;
輸出格式:字段展示形式,如時間、經緯度等;
配置表定製:主要是部分業務邏輯須要根據配置表定製,如深度返回字段等;
模型鏈接:原子能力服務儘量獨立,同時也沒法枚舉定義模型關係,可是定製業務需求須要大量關聯透出,減小業務請求下降延時,因此模型自由關聯能力是必要的,因爲本方案最終的查詢控制在內部,對外暴露REST API,所以不會關聯自由度形成的難理解性並非一個問題。
須要經過嵌入簡單的DSL實現:
內置和自定義函數功能;
模型動態關聯查詢,上下文參數獲取;
能夠方便擴展自定義函數。
這裏嵌入DSL須要控制好度,由於DSL若是過於複雜,那麼,使用者或者發佈者沒法快速寫出查詢的話,對比寫代碼提效就會打折扣,偏離原本的價值,因此基本原則是簡單、可擴展。
因爲以前每一個API的定製開發基本全部功能混合在一塊兒,能複用部分就是鑑權提供裝飾器,常規性的響應格式定製提供一些工具函數,任何需求變動都須要變動代碼,走發佈流程,有了上面第一步的改造,這個步驟指望將非業務數據部分的定製功能抽象出處理鏈,每一個處理節點提供多實現(包含通用和定製),經過數據庫存儲插件鏈實現編排。
車線業務因爲鑑權方式須要根據客戶定製,所以存在多樣性,實現上是經過Web中間件實現多種鑑權插件:
HTTP簽名,參考這裏:主要面向ToB(車廠後臺、合做方)的請求;
JWT認證:主要面向車機、手機等終端;
API Key。
對於API網關來講,這些鑑權插件並無什麼不一樣之處,只是工程要處理一些定製場景,好比對於不一樣車廠的JWK管理刷新策略,JWT驗證策略等,具體須要根據業務訴求抽象建模,經過插件屬性來實現配置控制。
另外,網關還實現了一些變換器,主要用於將GraphQL的輸出變換爲REST API接口透出,這一方面因爲一些舊接口要作兼容支持,另外,一些重點客戶的全球化架構背景下本身已經徹底定義好了接口式樣,目前主要實現了:
入參變換:使用REST API參數填充GraphQL查詢模板;
Header變換:主要用於適配不一樣客戶規範;
JSON變換,使用場景以下:
可複用標準接口,可是不一樣客戶的響應結構規範不一致
定製非標接口,須要對GraphQL輸出進行轉換
而插件的使用則經過控制檯或API實現將插件配置信息存儲於數據庫中進行管理,使用時根據請求特徵從DB中提取並緩存起來使用。
改造後的新架構以下:
經過上述改造,將車聯網在線服務開發模式進行了升級,實現API控制檯動態發佈,大幅提高定製開發效率:
定製化開發佔比降低60%;
單接口開發從2-3人日→2-3人時。