前言
不同客戶端通常需要不同資料;不同客戶端通過不同型別的網路訪問服務,擁有單一、適合所有客戶端的API通常沒有意義;
這是一本關於微服務架構設計方面的書,這是本人閱讀的學習筆記。下面對一些符號做些說明:
()為補充,一般是書本里的內容;
[]符號為筆者筆注;
1. 外部API的設計難題
1.1 FTGO應用程式的服務及客戶端
- 使用服務API的客戶端一共有四種:
- Web應用程式;
- 在瀏覽器中執行的JavaScript應用程式;
- 移動應用程式;
- 由第三方開發人員編寫的應用程式;
- 其弊端有:
- 細顆粒度服務API要求客戶端發出多個請求以檢索所需的資料,這樣做效率低,並且可能導致糟糕的使用者體驗;
- 由於客戶端了解每項服務以及服務的API從而導致封裝不足(緊耦合),因此今後很難更改服務的架構和API;
- 服務可能適用對客戶端而言不便或不能使用的程式間通訊機制,尤其是防火牆外的客戶端;
1.2 FTGO移動客戶端API的設計難題
上述設計方案難處在於:
- 多次客戶端請求導致使用者體驗不佳 [考慮到行動網路的時延與多次請求的耗電量];
- 缺乏封裝導致前端開發做出的程式碼修改影響後端 [有時會破壞現有客戶端來修改API,導致舊版本不相容];
- 服務可能選用對客戶端不友好的程式間通訊機制 [有些協議無法通過防火牆];
1.3 其他型別客戶端API的設計難題與特點
- Web應用程式的API設計特點:
- 有較高的網路頻寬和較低的延遲;
- 可以使用非Web友好的協議訪問服務;
- 可以輕鬆更新Web應用程式;
- 基於瀏覽器JavaScript應用程式的API設計特點與難題:
- 服務API變化時,基於瀏覽器JavaScript應用程式很容易更新;
- 與移動端有相同的網路延遲問題;
- 基於瀏覽器的使用者介面,需要組合更多服務;
- 為第三方應用程式設計API:
- 組合API導致低效率;
- 必須花長時間維護舊版本;
2. API Gateway模式
使用API Gateway模式可以解決上述問題;
- API Gateway模式:實現一個服務,該服務是外部API客戶端進入基於微服務應用程式的入口點;
2.1 API Gateway實現的功能
2.1.1 請求路由
- 收到請求時,API Gateway會查詢路由對映,該對映指定將請求路由到哪個服務;
2.1.2 API組合
- 其提供粗顆粒度API,使移動客戶端能夠通過單個請求檢索所需的資料;
2.1.3 協議轉換
- 在需要時,某些API的操作實現在RESTful外部API和基於內部的gRPC API之間進行轉換;
2.1.4 能夠為每一個客戶端提供它們專用的API
- 可以為Android和iPhone移動應用程式提供不同的API,還將為第三方開發人員實現公共API;
2.1.5 實現邊緣功能
- 可以在三個不同位置實現邊緣功能:
- 在後端服務:相較於邊緣上進行身份驗證不安全;
- 在API Gateway上游的邊緣服務:好處是可以分隔問題、集中關鍵邊緣功能的職責;弊端是額外的請求跳躍增加網路延遲狀況、增加程式複雜性;
- 在API Gateway中實現邊緣服務:可以減少網路跳躍、改善延遲狀況、降低複雜性;提高安全性,詳情見【第11章 API Gateway與服務協作實現安全性】;
- 邊緣功能:
- 身份驗證:驗證發出請求的客戶端身份;
- 訪問授權:驗證客戶端是否有權執行該特定操作;
- 速率限制:限制特定客戶或所有客戶端每秒的請求數;
- 快取:快取響應以減少對服務的請求數;
- 指標收集:收集有關API使用情況的指標,以進行計費分析;
- 請求日誌:記錄請求歷史;
2.2 API Gateway的架構
圖解:
- 兩層架構:
- API層:由一個或多個獨立的API模組組成;
- 公共層:實現共享功能、邊緣功能,如身份驗證;
- 三個API模組:
- 移動裝置API:為FTGO移動客戶端實現API;
- 瀏覽器API:為瀏覽器中執行的JavaScript應用程式實現API;
- 公共API:為第三方開發人員實現API;
- 使用兩種方式實現每個API操作:
- 直接對映到單個服務API操作;
- 使用組合實現其他複雜API操作;
2.3 API Gateway的所有者模式
- 客戶端團隊擁有與他們有關的API模組並公開API;
- API Gateway團隊負責開發公共模組和API Gateway的運維;
- API Gateway的部署流水線必須完全自動化;否則,客戶端團隊不得不等待API Gateway團隊手工部署一個新的版本;
- 問題:多個團隊為相同的程式碼庫做貢獻,職責模糊;
- 解決辦法:使用後端前置模式
2.4 API Gateway的後端前置模式
- 後端前置模式:為每種型別的客戶端實現單獨的API Gateway;
- 理想情況下,所有API Gateway都使用相同的技術棧;
- 公共層的功能由API Gateway團隊實現;
- 好處:明確界定職責、API彼此隔離提高可靠性、提高可觀測性、每個API獨立可擴充套件、減少啟動時間;
2.5 API Gateway模式的好處與弊端
好處:
- 封裝應用程式的內部;
- 減少客戶端與應用程式之間的往返次數;
- 簡化客戶端程式碼;
弊端:
- 開發人員必須更新API Gateway才能對外公開服務的API;
- 更新API Gateway的過程儘可能輕量化;
2.6 API Gateway的設計難題
- 效能和可擴充套件性:影響效能和可擴充套件性的關鍵設計決策是API Gateway使用同步還是非同步I/O;
- 同步I/O:每個網路連線由專用執行緒處理;限制是作業系統執行緒是重量級的,API Gateway可擁有的執行緒數量和併發連線數量存在上限;
- 非同步(非阻塞)I/O:單個事件迴圈執行緒將I/O請求分派給事件處理程式;具有可擴充套件性;弊端是比基於非同步回撥的程式設計模型要複雜得多,程式碼更難編寫、理解和除錯;使用非阻塞I/O是否具有意義的整體優勢取決於API Gateway的請求處理邏輯特性;
- 使用響應式程式設計抽象編寫可維護的程式碼:
- 當服務之間沒有依賴關係時,應該儘可能同時呼叫服務,以縮短響應時間;
- 使用傳統的非同步回撥方法編寫API組合程式碼會導致“回撥地獄”,可以以宣告式風格編寫API組合程式碼;
- 處理區域性故障:
- 可以在負載均衡器後面執行多個API Gateway例項實現可靠性;
- 對於失敗服務未完成的請求可以使用斷路器模式提高可靠性,詳情見【第3章 斷路器模式】;
- 成為應用程式架構中的好公民:
- 與其他服務一樣API Gateway必須實現整個架構中選擇的各種模式;
- 如:服務發現模式【第三章】;可觀測性模式【第十一章】;
3. 實現一個API Gateway
3.1 實現API Gateway的兩種方法
- 使用現成的API Gateway產品或服務:幾乎不需要程式碼開發,但靈活性最低;如:現成的API Gateway通常不支援API組合;
- 使用API Gateway框架或Web框架作為起點,開發屬於自己的API Gateway:最靈活的方法,但需要進行一些開發工作;
3.2 使用現成的API Gateway產品或服務
- AWS API Gateway
- AWS Application Load Balancer
- 使用產品化的API Gateway;
3.3 使用Netflix Zuul開發API Gateway
- 開發API Gateway需要解決兩個問題:
- 實現定義路由規則的機制以簡化複雜的程式碼;
- 正確實現HTTP代理行為,包括如何處理HTTP標頭;
- Zuul使用過濾器的概念,可重用請求攔截器;
- Zuul通過一系列適用的過濾器來處理HTTP請求,然後轉換請求,呼叫後端服務,並在響應傳送回客戶端之前轉換響應;
- 限制:它只能實現基於路徑的路由,無法實現【第7章】描述的查詢架構;
3.4 使用Spring Cloud Gateway開發API Gateway
- Spring Cloud Gateway是一個基於多個框架構建的API Gateway框架,屬於響應式Web框架,構建在Project Reactor之上;
- Project Reactor是一個基於NIO的JVM響應式框架;
- 其提供一種簡單而全面的方法執行以下操作:
- 將請求路由到後端;
- 實現執行API組合的請求處理程式;
- 處理邊緣功能,例如身份驗證;
3.5 Spring Cloud Gateway的關鍵部分
圖解:
- ApiGatewayMain包:定義API Gateway的主程式;
- 一個或多個API包:一個API包實現一組API端點;如,Orders包實現與Order相關的API端點;
- 代理程式包:由API程式包用於呼叫服務的代理類組成;
- OrderConfiguration類:定義了一些Spring beans,它們負責路由與Order相關的請求;
- orderProxyRoutes @Bean:定義了將API操作對映到後端服務URL的規則;路由規則可以匹配HTTP方法、標頭和路徑的某些組合;
- orderHandlers @Bean:定義了覆蓋orderProxyRoutes的規則;這些規則描述了將API操作對映到處理程式的具體方法;
- orderHandlers類:實現各種請求處理程式方法,此方法使用API組合來獲取訂單詳細資訊;處理程式的方法使用遠端代理類(如OrderService)呼叫後端服務;
3.5.1 OrderConfiguration類
-
OrderConfiguration類是一個Spring @Configuration類,它定義了實現 /Orders端點的Spring @Bean;
-
OrderDestinations是一個Spring @ConfigurationProperties類,它支援後端服務URL的外部配置;
3.5.2 OrderHandlers類
- OrderHandlers類定義了實現自定義行為的請求處理程式方法,包括API組合;
3.5.3 OrderService類
- OrderService類是Order Service的遠端代理;
3.5.4 ApiGatewayApplication類
- ApiGatewayApplication類實現了API Gateway的main()方法,它是Spring Boot main類;
- @EnableGateway註解匯入Spring Cloud Gateway框架的Spring配置;
3.6 使用GraphQL實現API Gateway
GraphQL是一種基於影像的API框架,其旨在支援高效的資料提取;
圖解:
- 基於圖形的模式定義了一組節點(型別),它們具有屬性(欄位)和其他節點的關係;
3.7 基於GraphQL的FTGO API Gateway的設計
其關鍵部分:
- GraphQL模式:定義伺服器端資料模型及其支援的查詢;
- 解析器函式:解析函式將模式的元素對映到各種後端服務;
- 代理類:代理類呼叫FTGO應用程式的服務;
4. 本章小結
- 應用程式的外部客戶端通常利用API Gateway訪問應用程式的服務。API Gateway為每個客戶端提供自定義API。它負責請求路由、API組合、協議轉換以及邊緣功能(如身份驗證)的實現;
- 應用程式可以具有單個API Gateway,也可以使用後端前置模式,該模式為每種型別的客戶端定義API Gateway。後端前置模式的主要優點是它為客戶端團隊提供了更大的自主權,因為他們可以開發、部署和運維自己的API Gateway;
- 可以使用許多種技術來實現API Gateway,包括現成的API Gateway產品。或者,也可以使用框架開發自己的API Gateway;
- Spring Cloud Gateway是一個易於使用的良好框架,用於開發API Gateway。它使用任何屬性(包括方法和路徑)路由請求。Spring Cloud Gateway可以將請求直接路由到後端服務或自定義處理程式方法。它採用可擴充套件、響應式的Spring Framework 5 和Project Reactor框架構建。可以使用,例如,Project Reactor的Mono抽象,以響應式風格編寫自定義請求處理程式;
- GraphQL是一個提供基於圖形的查詢語言框架,是開發API Gateway的另一個很好的基礎。你可以編寫一個面向圖形的模式來描述服務端資料模型及其支援的查詢。然後,通過編寫檢索資料的解析器,將該模式對映到你的服務。基於GraphQL的客戶端對模式執行查詢,該模式準確指定伺服器應返回的資料。因此基於GraphQL的API Gateway可以支援不同的客戶端;