由淺入深瞭解羚瓏平臺統一接入服務 —— Monet

一、背景介紹

羚瓏作爲一款智能設計平臺,簡單易懂、可視化操作,同時擁有大量模板與素材爲用戶、商家或業務團隊節省了大量作圖時間從而達到降本增效。

隨着使用的用戶越來越多,同時業務也不斷在增長,這也給羚瓏服務端帶來了挑戰。


羚瓏服務端目前架構如圖所示由多個平臺組成,每個平臺都有自己的域名。隨着業務增長每次都是啓動一個平臺來擴展功能,這種模式弊端也顯現出來了。

對於後端同學來說,新建一個平臺需要對接登錄與權限;提供的 API 功能沒有集中管理,不清楚正在開發的 API 是否有重複提供;開發的 API 在某些業務場景下還需要自行限流或降級;缺少全局 API 監控。

對於運維同學來說,要爲後端同學開發完成的每個平臺新建域名映射(同時還需要申請證書)。

對於前端同學來說,爲了複用某些 API 功能還需要對接多個域名,同時還區分測試與生產環境域名,這就導致前端同學在項目中還需要維護一批域名。

根據以上場景,我們可以總結爲,缺少 API 的統一入口與管理(統一域名)、統一鑑權、統一流控、統一監控。

如何解決以上架構痛點?我們需要一個服務承載在業務平臺之上接收前端的請求,轉發到相應的後端平臺上,還可以對每個請求進行用戶認證與權限校驗,還可以對 API 精準限流與降級,同時對 API 請求響應異常進行監控上報。

這個服務就呼之欲出:API 網關,並取名爲:Monet。下面我將介紹下這個網關中間件服務。


二、技術選型

確定了 Monet 需求之後,我們就開始進行技術選型。

基礎框架選擇

牛頓說過,如果說我別人看得更遠些,那是因爲我站在了巨人的肩膀上。所以我們需要站在巨人的肩膀纔可以看得更遠。那麼 Monet 也一樣,需要選取一款網關的框架,並在此基礎之上進行擴展。

在技術選型需要從語言體系、社區活躍度、擴展性、性能等角度考慮。我們從社區活躍度比較高的選出了兩個分類:非 Java 語言網關:Nginx、Kong、Traefik;Java 語言網關:Spring Cloud Gateway 與 Spring Cloud Zuul 2。

由於後端採用 Java 的 Spring 生態開發的,所以在編程語言一致性上更加傾向 Java 語言開發的組件。所以在 Spring 生態中有兩款網關可供選擇,分別是:Spring Cloud Gateway 與 Spring Cloud Zuul 2

Spring Cloud Gateway 由官方主推網關,Zuul 2 由 Netfix 公司開源的網關。兩者在實際生產使用性能相比沒有差距,Spring Cloud Gateway 基於 Spring 5.0、Spring Boot 2.0 與 Project Reactor,爲服務提供一個簡單有效的 API 網關;而 Zuul 1 基於同步 IO 與 Zuul 2 基於 Netty Server 異步 IO,都是 Spring Cloud 生態中的組件。以下兩者一些區別:

網關 Spring Cloud Gateway Spring Cloud Zuul 2
易用性 簡單易用 參考資料較少
可維護性 Spring 系列可擴展強,易配置可維護性好 可維護性差
成熟度 Spring 社區成熟,但 Gateway 資源較少 開源不久,資料少

兩者相比之下,Spring Cloud Gateway 更具有接入的優勢。所以我們最終選擇了 Spring Cloud Gateway 作爲基礎框架


三、落地實現

在前面介紹到我們需要 Monet 來完成統一 API 入口與管理、統一鑑權、統一流控與統一監控。接下來一一介紹實現。

統一 API 入口與管理

統一 API 入口

統一 API 入口比較簡單,我們只需要將一個域名解析到 Monet,Monet 基於 Spring Cloud Gateway 實現,可通過路由配置即可實現將請求轉發到相應服務。這裏講述一下我們實現過程遇到的問題,首先 Spring Cloud Gateway 的路由配置有兩種:項目配置文件和基於代碼路由配置

以上兩種都有個弊端,那就是一旦路由配置有變更,都需要將 Monet 服務重啓,在實際生產環境中不太可取。

在查詢了一些資料發現,可以通過 RouteDefinitionRepository 接口實現獲取路由配置信息,我們可以實現從數據庫中獲取路由配置信息,當我們變更了路由配置之後,觸發 Spring Cloud Gateway 路由配置重載事件,就可以讓 Monet 獲取到最新的路由配置從而達到動態路由的效果,所以我們可以擴展爲以下流程:

統一 API 管理

爲什麼要做 API 管理呢?API 管理主要爲了避免 API 重複建設與 API 安全。

Monet 如何識別請求 URI 是屬於哪個 API 呢?要知道在 Restful API 中 URI 目錄中是帶有參數的,給 Monet 識別是哪個 API 帶來一定難度,但不是不可解。

可以利用 前綴樹 數據結構來 API 解析與匹配,前綴樹又叫單詞查找樹,典型應用於統計、排序等等,利用字符串的公共前綴來減少查詢時間,最大限度地減少不必要的字符串比較,從而提高匹配的速度。將 API URI 部分拆分字符串後的樹結構示意圖:

我們通過實現 Spring Cloud Gateway 的 GlobalFilter 實現 API 解析與監管,通過後端服務導出 API 信息導入到網關控制檯(利用 Zookeeper 存儲 API 信息),API 解析過濾器也是從 Zookeeper 獲取API 信息並緩存,如果找不到匹配 API 只能響應 404,能匹配上 API 的將解析出來的結果放到上下文中,方便後面的過濾器得到 API 信息進行下一步操作,例如權限校驗等等;

同時我們也會在網關控制檯建立審覈制度,得需要項目負責人審覈後方可將 API 上線。

統一鑑權

統一鑑權也分爲兩部分:用戶認證與權限校驗。

用戶認證

爲了讓後端服務無需關注登錄流程,用戶登錄認證的過程只需要在 Monet 完成,與 API 解析過濾器一樣,用戶認證也是通過 GlobalFilter 實現形成 Monet 的過濾器,用戶認證完了之後每個請求都能讀取到用戶的相關信息並且放入到上下文中,便於後面的過濾器或者後端服務獲取到。如圖所示:

權限校驗

爲了能夠讓後端服務將權限集中管理,特地形成了一套權限體系,並且專門由一個服務負責,並且根據後端服務需求在權限服務上進行自定義即可形成各個服務權限,權限服務就不在此過多講述。由於前面 API 解析已經能夠得到 API 信息與用戶認證得到的用戶信息,我們就可以對當前用戶進行權限校驗了。

統一流控

由於現在的限流與熔斷組件都非常成熟了,我們直接在 Spring Cloud Gateway 所支持的限流與熔斷的組件進行選型,支持限流熔斷組件有:Hystrix 與 Sentinel,兩個組件區別:

功能 Sentinel Hystrix
成熟度 社區活躍,文檔較全 已經停止維護
熔斷降級策略 基於響應時間、異常比率、異常數 基於異常比率
實時統計實現 滑動窗口 滑動窗口
動態規則配置 支持多種數據源 支持多種數據源
擴展性 多個擴展點 插件形式
限流 基於 QPS,支持基於調用關係的限流 優先支持
流量整形 支持預熱模式、勻速器模式、預熱排隊模式(流量規則可配置) 不支持
系統自適應保護 支持 不支持

根據以上功能區別我們最終選擇 Sentinel ,Sentinel 功能豐富同時我們可將相關限流與熔斷的配置規則放進 Zookeeper 便於我們在網關控制檯上進行配置,通過 Sentinel 可以對用戶、IP、或者 API 級別進行限流或者熔斷降級能力。

統一監控

API 的監控也是比較簡單,也是通過實現 GlobalFilter 並且在 API 解析之後,拿到 API 信息並記錄請求信息上報,例如:API 請求時間、響應耗時等數據。在此處爲了能夠適配各種監控系統,在此處定義了一套監控接口,只需要實現該接口即可實現不同監控系統,例如:內部版本接入京東內部監控系統,對應的就是獨立一個實現;同時可根據監控接口對接另外一套監控平臺,更具有擴展性。

以上就是完整的 Monet 架構。

四、總結

我們先通過介紹目前架構的痛點講述項目背景及技術選型,基於 Spring Cloud Gateway 落地實現 Monet 中的 統一入口與 API 管理、統一鑑權、統一流控、統一監控。雖然完成了以上功能,但是其實還有很多需要擴展的地方,例如:API 管理的審覈流程、接入非 Java 服務、Access 日誌等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章