目錄
- 什么是API網關
- 為什么需要API網關
- 前言
- 問題列表
- API網關解決了什么問題
- 常見的網關解決方案
- Nginx+Lua
- Spring Cloud Netflix Zuul
- SpringCloud Zuul的IO模型
- 弊端
- Spring Cloud Gateway
- 第二代網關——Gateway
- Gateway的特征
- Spring Cloud Gateway的處理流程
- Spring Cloud Gateway的相關概念
- Route(路由)
- Predicate(斷言)
- Filter(過濾器)
- 案例
- 需求
- 搭建Gateway微服務網關
- 1.創建項目
- 2.添加Gateway依賴
- 3.修改配置——基礎URI的路由配置方式
- 配置解析
- 網關過濾器
- 為網關添加過濾器
- 1.在上述案例的基礎上,創建AuthGlobalFilter并實現GlobalFilter、Ordered接口
- 2.重寫方法
- 3.filter方法驗證token參數
- 4.添加過濾器定義
- 5.驗證
什么是API網關
- API Gateway(API 網關),顧名思義,是出現在系統邊界上的一個面向 API 的、串行集中式的強管控服務,這里的邊界是企業 IT 系統的邊界,可以理解為企業級應用防火墻,主要起到隔離外部訪問與內部系統的作用。在微服務概念的流行之前,API 網關就已經誕生了,例如銀行、證券等領域常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的問題列表。
- API 網關的流行,源于近幾年來移動應用與企業間互聯需求的興起。移動應用、企業互聯,使得后臺服務支持的對象,從以前單一的Web應用,擴展到多種使用場景,且每種使用場景對后臺服務的要求都不盡相同。這不僅增加了后臺服務的響應量,還增加了后臺服務的復雜性。隨著微服務架構概念的提出,API網關成為了微服務架構的一個標配組件。
- API 網關是一個服務器,是系統對外的唯一入口。API 網關封裝了系統內部架構,為每個客戶端提供定制的 API。所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有非業務功能。API 網關并不是微服務場景中必須的組件。
為什么需要API網關
前言
- 不同的微服務一般會有不同的網絡地址,而外部客戶端可能需要調用多個服務的接口才能完成一個業務需求,如果讓客戶端直接與各個微服務通信,會有以下的問題
問題列表
- 客戶端會多次請求不同的微服務,增加了客戶端的復雜性。
- 存在跨域請求,在一定場景下處理相對復雜。
- 認證復雜,每個服務都需要獨立認證。
- 難以重構,隨著項目的迭代,可能需要重新劃分微服務。例如,可能將多個服務合并成一個或者將一個服務拆分成多個。如果客戶端直接與微服務通信,那么重構將會很難實施。
- 某些微服務可能使用了防火墻 / 瀏覽器不友好的協議,直接訪問會有一定的困難。
API網關解決了什么問題
常見的網關解決方案
Nginx+Lua
- Nginx 適合做門戶網關,是作為整個全局的網關。
- Gateway 可以實現熔斷、重試等功能,這是 Nginx 不具備的。
Spring Cloud Netflix Zuul
- Zuul 是 Netflix 公司開源的一個 API 網關組件,Spring Cloud 對其進行二次基于 Spring Boot 的注解式封裝做到開箱即用。
- 可以做到請求轉發,根據配置或者默認的路由規則進行路由和 Load Balance,無縫集成 Hystrix。
SpringCloud Zuul的IO模型
- Zuul 是Netflix出品的開源微服務網關,可與 Eureka、Ribbon、Hystrix 等組件配合使用,
- Zuul 的核心是一系列過濾器
- Spring Cloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是傳統的Servlet IO處理模型。
弊端
- servlet是一個簡單的網絡IO模型,當請求進入servlet container時,servlet container就會為其綁定一個線程,在并發不高的場景下這種模型是適用的
- 但是一旦并發上升,線程數量就會上漲,而線程資源代價是昂貴的(上線文切換,內存消耗大)嚴重影響請求的處理時間。
- 在一些簡單的業務場景下,不希望為每個request分配一個線程,只需要1個或幾個線程就能應對極大并發的請求,這種業務場景下servlet模型沒有優勢。
Spring Cloud Gateway
- Spring Cloud官方推出的第二代網關框架,性能顯著提升;
第二代網關——Gateway
- SpringCloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。
- SpringCloud Gateway 作為 Spring Cloud 生態系統中的網關,目標是替代 Zuul。而為了提升網關的性能,SpringCloud Gateway是基于WebFlux框架實現的,而WebFlux框架底層則使用了高性能的Reactor模式通信框架Netty。
- Spring Cloud Gateway 的目標,不僅提供統一的路由方式,并且基于 Filter 鏈的方式提供了網關基本的功能,例如:安全,監控/指標,和限流。
Gateway的特征
- 基于Spring Framework 5、Project Reactor和Spring Boot 2.0構建
- 能夠在任意請求屬性上匹配路由
- predicates(謂詞) 和 filters(過濾器)是特定于路由的
- 集成了Hystrix斷路器
- 集成了Spring Cloud DiscoveryClient
- 易于編寫謂詞和過濾器
- 請求速率限制
- 路徑重寫
Spring Cloud Gateway的處理流程
- 客戶端向 Spring Cloud Gateway 發出請求。
- 然后在 Gateway Handler Mapping 中找到與請求相匹配的路由,將其發送到 Gateway Web Handler。
- Handler 再通過指定的過濾器鏈來將請求發送到我們實際的服務執行業務邏輯,然后返回。
- 過濾器之間用虛線分開是因為過濾器可能會在發送代理請求之前(“pre”)或之后(“post”)執行業務邏輯。
Spring Cloud Gateway的相關概念
Route(路由)
- 網關配置的基本組成模塊,和Zuul的路由配置模塊類似。
- 一個Route模塊由一個 ID,一個目標 URI,一組斷言和一組過濾器定義。
- 如果斷言為真,則路由匹配,目標URI會被訪問。
Predicate(斷言)
- 這是一個 Java 8 的 Predicate,可以使用它來匹配來自 HTTP 請求的任何內容,
- 例如 headers 或參數。斷言的輸入類型是一個 ServerWebExchange。
Filter(過濾器)
- 和Zuul的過濾器在概念上類似,可以使用它攔截和修改請求,并且對上游的響應,進行二次處理。
- 過濾器為
org.springframework.cloud.gateway.filter.GatewayFilter
類的實例。
案例
需求
- 提供三個微服務EurekaServer、Consumer端、Provider端
- 通過網關轉發微服務請求
- 要求訪問Gateway網關,然后轉發請求到Consumer端,然后繼續調取Provider端服務
搭建Gateway微服務網關
1.創建項目
指定artifactId為:demo-gateway
2.添加Gateway依賴
- 還要添加Spring Cloud依賴,此處省略
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
3.修改配置——基礎URI的路由配置方式
- 指定服務端口、Eureka Server地址等信息
spring:application:name: demo-gatewaycloud:gateway:routes:- id: user-consumer-1uri: lb://demo-user-consumerpredicates:- Path=/api/user/**config:uri: http://localhost:7600label: devprofile: dev
eureka:client:service-url:defaultZone: http://192.168.2.220:7776/eureka
配置解析
屬性 | 解釋 |
---|---|
id | 我們自定義的路由 ID,保持唯一 |
uri | 目標服務地址, lb代表從注冊中心獲取服務 |
predicates | 路由條件,Predicate 接受一個輸入參數,返回一個布爾值結果。該接口包含多種默認方法來將 Predicate 組合成其他復雜邏輯。 |
Path | 轉發地址格式 |
filters | 過濾器鏈 |
StripPrefix | 作用是去掉請求路徑的最前面n個部分截取掉,StripPrefix=1就代表截取路徑的個數為1,比如前端過來請求http://localhost:8085/user/login,匹配成功后,路由到后端的請求路徑就會變成http://localhost:8082/login |
網關過濾器
- 每個服務在處理請求的時候都要判斷是否驗證token
- 需要驗證token是否有效
- 效率低
- 每個請求都需要轉發到具體的微服務后再判斷,然后將判斷的結果回轉給網關
- 在網關轉發前就行進過濾處理
- 過濾器
為網關添加過濾器
創建網關過濾器
1.在上述案例的基礎上,創建AuthGlobalFilter并實現GlobalFilter、Ordered接口
2.重寫方法
- filter:過濾器實現
- getOrder():過濾順序
3.filter方法驗證token參數
public class AuthGlobalFilter implements org.springframework.cloud.gateway.filter.GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token = exchange.getRequest().getHeaders().getFirst("token");if (token == null || token.isEmpty()) {System.out.println("token為空,不能通過");exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}
}
4.添加過濾器定義
修改啟動類,添加方法
@Beanpublic AuthGlobalFilter globalFilter() {return new GlobalFilter();}
5.驗證
- 請求接口
- 分別攜帶token和不攜帶token驗證請求結果