一、概述
在微服務架構中,每個服務都是一個可以獨立開發和執行的元件,而一個完整的微服務架構由一系列獨立執行的微服務組成。其中每個服務都只會完成特定領域的功能,比如訂單服務提供與訂單業務場景有關的功能、商品服務提供商品展示功能等。各個微服務之間通過輕量級通訊機制 REST API 或者 RPC 完成通訊。 微服務之後在某些層面會帶來一定的影響,比如,一個使用者檢視一個商品的詳情,對於客戶端來說,可能需要呼叫商品服務、評論服務、庫存服務、營銷服務等多個服務來完成資料的渲染在這個場景中,客戶端雖然能通過呼叫多個服務實現資料的獲取,但是會存在一 些問題,比如:
- 客戶端需要發起多次請求,增加了網路通訊的成本及客戶端處理的複雜性。
- 服務的鑑權會分佈在每個微服務中處理,客戶端對於每個服務的呼叫都需要重複鑑權。
- 在後端的微服務架構中,可能不同的服務採用的協議不同,比如有 HTTP、RPC 等。客戶端如果需要呼叫多個服務,需要對不同協議進行適配
二、微服務閘道器的作用
所以,我們可以在微服務之前增加一個前置節點,這個節點就是閘道器,閘道器就是一個網路連線到另一個網路的“關口”。也就是網路。而在微服務架構中,它不僅僅只是一個網路互連的一個關口,還有更多的作用,以前面分析的這個場景為例,增加閘道器之後所有請求的下發都由閘道器下發;對於商品詳情展示的場景來說,增加了 API 閘道器之後,在 API 閘道器層可以把後端的多個服務進行整合,然後提供一個唯一的業務介面,客戶端只需要呼叫這個介面即可完成資料的獲取及展示。在閘道器中會再去消費後端的多個微服務進行統一的整合,給客戶端返回一個唯一的響應。去消費後端的多個微服務進行統一的整合,給客戶端返回一個唯一的響應。
- 針對所有請求進行統一鑑權、限流、熔斷、日誌。
- 協議轉化。針對後端多種不同的協議,在閘道器層統一處理後以 HTTP 協議對外提供服務。
- 用過 Dubbo 框架的應該知道,針對 Dubbo 服務還需要提供一個 Web 應用來進行協議轉化。
- 統一錯誤碼處理。
- 請求轉發,並且可以基於閘道器實現內外網隔離
2.1、閘道器的作用
- 效能:API高可用,負載均衡,容錯機制。
- 安全:許可權身份認證、脫敏,流量清洗,後端簽名(保證全鏈路可信呼叫),黑名單(非法呼叫的限制)。
- 日誌:日誌記錄(spainid,traceid)一旦涉及分散式,全鏈路跟蹤必不可少。
- 快取:資料快取。
- 監控:記錄請求響應資料,api耗時分析,效能監控。
- 限流:流量控制,錯峰流控,可以定義多種限流規則。
- 灰度:線上灰度部署,可以減小風險。
- 路由:動態路由規則。
三、服務閘道器的要求
從上面的案例來看,閘道器成了所有流量的入口,那麼對於這樣一個角色來說,它需要在某些方面有很高的要求
- 穩定性,
- 安全性,防止惡意請求,以及保障資料傳輸的安全性
- 高效能、可用性,
- 閘道器作為所有流量的入口,那麼對於效能這塊的要求就非常高了,因為一旦閘道器的效能出現瓶頸,就算後端的服務效能再高,意義也不大
- 閘道器必須要支援叢集部署,這個是分散式架構的基本要求。否則閘道器服務掛掉就會導致整個系統不可用
- 擴充套件性,可維護性,對於定製化需求方面,如何實現可擴充套件;
常見的閘道器方案
- OpenResty(Nginx+lua)
- Kong,是基於openresty之上的一個封裝,提供了更簡單的配置方式。 它還提供了付費的商業外掛
- Tyk(開源、輕量級),Tyk 是一個開源的、輕量級的、快速可伸縮的 API 閘道器,支援配額和速度限制,支援認證和資料分析,支援多使用者多組織,提供全 RESTful API。它是基於go語言開發的元件。
- Zuul,是spring cloud生態下提供的一個閘道器服務,效能相對來說不是很高
- Spring Cloud Gateway,是Spring團隊開發的高效能閘道器
閘道器選型
- 部署和維護成本
- 開源還是閉源
- 是否私有化部署
- 功能是否滿足當前需求
- 社群資料的完善以及版本迭代和功能維護
四、Spring Cloud Gateway的核心概念
- Route 路由,它是閘道器的基礎元素,包含ID、目標URI、斷言、過濾器組成,當前請求到達閘道器時,會通過Gateway Handler Mapping,基於斷言進行路由匹配,當斷言為true時,匹配到路由進行轉發
- Predicate,斷言,學過java8的應該知道這個函式,它可以允許開發人員去匹配HTTP請求中的元素,一旦匹配為true,則表示匹配到合適的路由進行轉發
- Filter,過濾器,可以在請求發出的前後進行一些業務上的處理,比如授權、埋點、限流等。
它的整體工作原理如下。
其中,predicate就是我們的匹配條件;而filter,就可以理解為一個無所不能的攔截器。有了這兩個元素,再加上目標uri,就可以實現一個具體的路由了。客戶端向 Spring Cloud Gateway 發出請求,如果請求與閘道器程式定義的路由匹配,則該請求就會被髮送到閘道器 Web 處理程式,此時處理程式執行特定的請求過濾器鏈。過濾器之間用虛線分開的原因是過濾器可能會在傳送代理請求的前後執行邏輯。所有 pre 過濾器邏輯先執行,然後執行代理請求;代理請求完成後,執行 post 過濾器邏輯
五、應用實戰
新建一個spring-cloud-gateway服務
在spring-cloud-gateway服務中匯入以下包
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
然後在配置檔案中配置如下
server: port: 9100 spring: application: name: spring-cloud-gateway cloud: gateway: routes: - predicates: - Path=/service/** filters: #過濾 - StripPrefix=1 uri: http://localhost:8080/ eureka: instance: hostname: localhost client: serviceUrl: defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/ #指向服務註冊中心的地址
啟動專案通過閘道器訪問業務服務,發現可以直接通過閘道器的埠發起訪問
5.1、斷言
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#the-after-route-predicate-factory
這是官方提供的11種斷言方法,有興趣可以按官網的去配置玩下,cloud整個體系配置相對來說很簡單的
下面就寫一個關於常用的Cookie配置下;
5.2、自定義斷言
如果官網提供的斷言不滿足自己的要求,官網也支援自定義斷言;自定義斷言要繼承AbstractRoutePredicateFactory這個抽象工廠,我們自定義的斷言類名字尾必須是RoutePredicateFactory;自定義也很簡單也就是看別人怎麼寫的然後抄就完了
然後把之前測試工具的Cookies刪除,呼叫成功