車聯網服務non-RESTful架構改造實踐

amap_tech發表於2019-08-28

導讀

在構建面向企業專案、多端的內容聚合類線上服務API設計的過程中,由於其定製特點,採用常規的restful開發模式,通常會導致大量雷同API重複開發的窘境,本文介紹一種GraphQL查詢語言+閘道器編排聯合的實踐,解決大量重複定製的問題。

早期與車廠合作過程中,基於高德已有的資料、引擎能力和一些較為重要的相關CP服務(如停車場、加油站、天氣等),形成的線上服務協作模式是針對客戶需求,採用REST API提供針對每個車廠、每個專案以及每個終端提供不同的API實現,然而資料核心獨立服務實際上就有十餘種,然而由於車線業務維護週期長,定製多,2-3年下來,API規模已達幾百個,而且持續發散級增長,這給持續開發和維護帶來不小挑戰。

分解業務開發過程,無非兩類工作,業務需求能力資料的獲取和非業務訴求但是必不可少的如鑑權等通用化能力,當前來看,其實這兩個問題是幾乎所有業務團隊都會遇到的問題,因此解決方案也基本類似,如服務聚合、流程編排、API閘道器等。

本文簡要介紹下車聯網線上服務改造舊架構的一些實踐。

有關名詞

  • 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規範限制,一些定製難以實現,如:

  1. 入參定製:如引數關聯,型別轉換等;

  2. 輸出格式:欄位展現形式,如時間、經緯度等;

  3. 配置表定製:主要是部分業務邏輯需要根據配置表定製,如深度返回欄位等;

  4. 模型連線:原子能力服務儘可能獨立,同時也無法列舉定義模型關係,但是定製業務需求需要大量關聯透出,減少業務請求降低延時,所以模型自由關聯能力是必要的,由於本方案最終的查詢控制在內部,對外暴露REST API,因此不會關聯自由度造成的難理解性並不是一個問題。

需要透過嵌入簡單的DSL實現:

  • 內建和自定義函式功能;

  • 模型動態關聯查詢,上下文引數獲取;

  • 可以方便擴充套件自定義函式。

這裡嵌入DSL需要控制好度,因為DSL如果過於複雜,那麼,使用者或者釋出者無法快速寫出查詢的話,對比寫程式碼提效就會打折扣,偏離本來的價值,所以基本原則是簡單、可擴充套件。

業務無關功能透過API閘道器外掛配置化

由於之前每個API的定製開發基本所有功能混合在一起,能複用部分就是鑑權提供裝飾器,常規性的響應格式定製提供一些工具函式,任何需求變更都需要變更程式碼,走釋出流程,有了上面第一步的改造,這個步驟期望將非業務資料部分的定製功能抽象出處理鏈,每個處理節點提供多實現(包含通用和定製),透過資料庫儲存外掛鏈實現編排。

車線業務由於鑑權方式需要根據客戶定製,因此存在多樣性,實現上是透過Web中介軟體實現多種鑑權外掛:

  • HTTP簽名,參考這裡:主要面向ToB(車廠後臺、合作方)的請求;

  • JWT認證:主要面向車機、手機等終端;

  • API Key。

對於API閘道器來說,這些鑑權外掛並沒有什麼不同之處,只是工程要處理一些定製場景,比如對於不同車廠的JWK管理重新整理策略,JWT驗證策略等,具體需要根據業務訴求抽象建模,透過外掛屬性來實現配置控制。

另外,閘道器還實現了一些變換器,主要用於將GraphQL的輸出變換為REST API介面透出,這一方面由於一些舊介面要做相容支援,另外,一些重點客戶的全球化架構背景下自己已經完全定義好了介面式樣,目前主要實現了:

  • 入參變換:使用REST API引數填充GraphQL查詢模板;

  • Header變換:主要用於適配不同客戶規範;

  • JSON變換,使用場景如下:

  1. 可複用標準介面,但是不同客戶的響應結構規範不一致

  2. 定製非標介面,需要對GraphQL輸出進行轉換

而外掛的使用則透過控制檯或API實現將外掛配置資訊儲存於資料庫中進行管理,使用時根據請求特徵從DB中提取並快取起來使用。

改造後的新架構如下:

小結

透過上述改造,將車聯網線上服務開發模式進行了升級,實現API控制檯動態釋出,大幅提升定製開發效率:

  • 提效開發:正交化原子能力編排,透過輕量級定義取代定製化程式碼開發:
  1. 定製化開發佔比下降60%;

  2. 單介面開發從2-3人日→2-3人時。

  • 協議相容:混合REST方案,對外提供標準協議、支援既有適配協議。

關注高德技術,找到更多出行技術領域專業內容


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69941357/viewspace-2655284/,如需轉載,請註明出處,否則將追究法律責任。

相關文章