終身學習、樂于分享、共同成長!
前言
随着微服務架構的流行,一個系統會被拆分為很多個微服務。那麼作為用戶端要如何去調用這麼多的微服務呢?如果沒有網關的存在,我們隻能在用戶端記錄每個微服務的位址,然後分别去用。
這樣的架構,會存在着諸多的問題:
- 每個業務都會需要鑒權、限流、權限校驗、跨域等邏輯,如果每個業務都各自為戰,自己造輪子實作一遍,會很蛋疼,完全可以抽出來,放到一個統一的地方去做。
- 如果業務量比較簡單的話,這種方式前期不會有什麼問題,但随着業務越來越複雜,比如淘寶打開一個頁面可能會涉及到數百個微服務協同工作,如果每一個微服務都配置設定一個域名的話,一方面用戶端代碼會很難維護,涉及到數百個域名,另一方面是連接配接數的瓶頸,想象一下你打開一個APP,通過抓包發現涉及到了數百個遠端調用,這在移動端下會顯得非常低效。
- 後期如果需要對微服務進行重構的話,也會變的非常麻煩,需要用戶端配合你一起進行改造,比如商品服務,随着業務變的越來越複雜,後期需要進行拆分成多個微服務,這個時候對外提供的服務也需要拆分成多個,同時需要用戶端配合你進行改造,非常蛋疼。
上面的這些問題可以借助API網關來解決。
所謂的API網關,就是指系統的統一入口,它封裝了應用程式的内部結構,為用戶端提供統一服務,一些與業務本身功能無關的公共邏輯可以在這裡實作,諸如認證、鑒權、監控、路由轉發等等。
添加API網關之後,系統的架構圖變成了如下所示:
加上網關之後的微服務整體架構圖
Spring Cloud Gateway
Spring Cloud Gateway 是Spring Cloud生态系統中的微服務網關解決方案,它基于Spring5、Spring Boot2和Project Reactor等技術棧,提供了一種簡單而有效的方式來讓請求流量轉發到一個或多個後端服務。
Spring Cloud Gateway是Spring Cloud官方推出的第二代網關架構,定位于取代 Netflix Zuul1.0。相比 Zuul 來說,Spring Cloud Gateway 提供更優秀的性能,更強大的有功能。
Spring Cloud Gateway是由WebFlux + Netty + Reactor實作的響應式的API網關。它不能在傳統的 servlet 容器中工作,也不能建構成 war 包。
Spring Cloud Gateway 旨在為微服務架構提供一種簡單且有效的 API 路由的管理方式,并基于 Filter 的方式提供網關的基本功能,例如說安全認證、監控、限流等等。
Spring Cloud Gateway 具有以下主要特性:
- 基于路由的請求轉發:Spring Cloud Gateway 可以通過預定義的路由規則将請求轉發到不同的後端服務,進而實作負載均衡、熔斷降級等功能。
- 過濾器鍊:Spring Cloud Gateway 的過濾器鍊可以對請求進行多次處理,比如添加請求頭、修改請求體、驗證參數等操作。
- 支援非阻塞式 I/O 模型:Spring Cloud Gateway 基于 Reactor 提供了響應式程式設計模型,能夠更好地支援高并發、低延遲的場景。
- 高度可擴充:Spring Cloud Gateway 的路由規則和過濾器鍊都是基于 Java 代碼實作的,是以可以很容易地進行擴充和定制。
官方文檔:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html
核心概念
- 路由(route)
路由是網關中最基礎的部分,路由資訊包括一個ID、一個目的URI、一組斷言工廠、一組Filter組成。如果斷言為真,則說明請求的URL和配置的路由比對。
- 斷言(predicates)
Java8中的斷言函數,SpringCloud Gateway中的斷言函數類型是Spring5.0架構中的ServerWebExchange。斷言函數允許開發者去定義比對Http request中的任何資訊,比如請求頭和參數等。
- 過濾器(Filter)
SpringCloud Gateway中的filter分為Gateway FilIer和Global Filter。Filter可以對請求和響應進行處理。
工作原理
執行流程大緻如下:
- Gateway Client向Gateway Server發送請求
- 請求首先會被HttpWebHandlerAdapter進行提取組裝成網關上下文
- 然後網關的上下文會傳遞到DispatcherHandler,它負責将請求分發給RoutePredicateHandlerMapping
- RoutePredicateHandlerMapping負責路由查找,并根據路由斷言判斷路由是否可用
- 如果過斷言成功,由FilteringWebHandler建立過濾器鍊并調用
- 請求會一次經過PreFilter--微服務--PostFilter的方法,最終傳回響應
快速入門
下面通過一個簡單的示例來示範 Spring Cloud Gateway 的用法。
- 首先,在pom.xml中添加以下依賴項:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 然後,在bootstrap.yml中配置路由規則和過濾器鍊:
spring:
application:
name: gateway-server
cloud:
gateway:
routes:
- id: order-server # 目前路由的辨別,要求唯一
uri: http://localhost:8008 # 請求要轉發到的位址
order: 1 # 路由的優先級,數值越小,優先級越高
predicates: # 斷言(就是指路由轉發需要滿足的條件)
- Path=/order-server/** # 當請求路徑滿足Path指定的路徑時,才進行路由轉發
filters: # 過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改
- StripPrefix=1 # 轉發之前去掉1層路徑
- 內建Nacos
現在是在配置檔案中寫死了轉發位址,這樣非常不靈活,也難以維護,接下來通過注冊中心擷取服務名稱進行路由轉發。
首先引入Nacos服務注冊與發現依賴
<!--nacos-服務注冊發現-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
然後修改bootstrap.yml配置檔案的路由模式
spring:
application:
name: gateway-server # 應用名稱 (nacos會将該名稱當做服務名稱)
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml # 基于 dataId 為 yaml 的檔案擴充名配置方式
#namespace: d8f2135d-4ed8-42e4-8842-cdea14152b02 # 指定命名空間
#group: DEVELOP_GROUP
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: order-server # 目前路由的辨別,要求唯一
uri: lb://order-server # 請求要轉發到的位址,lb指的是從nacos中按照名稱擷取微服務,并遵循負載均衡政策
order: 1 # 路由的優先級,數值越小,優先級越高
predicates: # 斷言(就是指路由轉發需要滿足的條件)
- Path=/order-server/** # 當請求路徑滿足Path指定的路徑時,才進行路由轉發
filters: # 過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改
- StripPrefix=1 # 轉發之前去掉1層路徑
總結
- Spring Cloud Gateway 是Spring Cloud生态系統中的微服務網關解決方案,它基于Spring5、Spring Boot2和Project Reactor等技術棧,提供了一種簡單而有效的方式來讓請求流量轉發到一個或多個後端服務。
- Spring Cloud Gateway是由WebFlux + Netty + Reactor實作的響應式的API網關。它不能在傳統的 servlet 容器中工作,也不能建構成 war 包。
- 最後通過一個例子快速入門體驗網關的使用。
完整代碼可以在公衆号Seven的代碼實驗室中回複SpringCloudAlibaba擷取。
我是Seven,一個不懈努力的程式猿,希望本文能對你有所裨益