一、什么是網關
經常面試的人肯定知道,在去公司面試時,通常不會直接去面試官那里面試,而是先去前臺進行詢問面試官的所在地,并進行一些相關登記。而網關對于一個微服務項目來說,就類似于一個前臺,打到微服務中的請求通常都需要先到網關,由網關進行一些處理后,再打到相關服務上。
網關的處理具體包括以下幾個方面:
- 權限控制:對請求進行權限校驗,校驗失敗則直接將請求進行攔截。
- 動態路由:根據請求信息將請求轉發到對應的微服務上。
- 負載均衡:當請求的目標服務有多個時,根據情況進行負載均衡
- 限流:將請求按照設定的最大流量進行限流,以免各服務壓力過大?
目前市面上大多數都是使用Gateway來作為微服務的網關。
二、Gateway的使用
Gateway服務的搭建
1.在微服務中使用Gateway網關,首先我們得在微服務項目中創建一個新的模塊。
2.然后我們需要引入依賴,具體如下:
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies>
3.然后我們需要創建一個啟動類
此時,一個網關模塊就創建好了,但當前網關還沒有設置任何處理請求的功能,下面我們來看一下如何設置網關的功能。
Route Predicate Factories
在Java8中提供了一個函數式接口Predicate,這個接口能夠校驗請求中的參數,具體為通過接受一個字符串,根據字符串的特點返回一個布爾值,用來進行條件過濾。下面我們來具體使用一下這個接口。
1.首先我們來創建一個該接口的實現類
2.然后重寫其中的test方法
在test中我們可以定義一些邏輯來進行條件判斷,例如我們這里定義成字符串為空返回false,不為空返回true。
然后我們就可以使用這個類來進行一些參數判斷了
在Predicate中還包含了許多其它方法,例如and方法,它的參數為Predicate類型 ,返回值為一個新的Predicate,這個新的Predicate的test方法返回的則是前兩個Predicate的test返回值取”&&“的結果。其它方法可以參考下面的內容:
- isEqual(Object targetRef):?較兩個對象是否相等,參數可以為Null
- and(Predicate other):短路與操作,返回?個組成Predicate
- or(Predicate other):短路或操作,返回?個組成Predicate
- test(T t):傳??個Predicate參數,?來做判斷?
- negate():返回表?此Predicate邏輯否定的Predicate
Gateway給我們提供了一個 Route Predicate Factories(路由斷言工廠),里面包含了很多的Predicate來對路由進行一些規則匹配,例如Path,它能匹配指定規則的路徑,Methond能夠匹配指定的請求方法,還有其它的一些Predicate,大家可以去下面這個鏈接進行查詢:
https://docs.spring.io/spring-cloud-gateway/reference/spring-cloudgateway/request-predicates-factories.html
我們可以在我們創建的Gateway模塊的配置文件中來使用這些Predicate,具體使用的配置如下:
gateway:routes: # ?關路由配置- id: product-service #路由ID, ?定義, 唯?即可uri: lb://product-service #?標服務地址predicates: #路由條件- Path=/product/**- id: order-serviceuri: lb://order-servicepredicates:- Path=/order/**
配置好之后,當請求的url與predicates中對于的路由規則path匹配時,就會依據id中的服務名稱,去注冊中心獲取對應的服務地址,然后負載均衡出一個地址并構建對應的請求去訪問目標服務。
例如我們去訪問下面這個地址:
http://127.0.0.1:8080/order/1
此時請求就會來到網關,在網關中進行predicate的條件判斷,判斷通過后去Nacos獲取服務信息并負載均衡嗎,然后去訪問目標服務。上面地址的訪問結果如下:
可以發現成功返回了數據,由此可以推斷,請求成功通過網關訪問到了目標服務。
如果我們的請求不符合定義的匹配規則,則不會訪問到目標服務,例如我們訪問下面這個?路徑http://127.0.0.1:8080/feign/1(也是order-service里面的)
我們也可以配置多個predicate,例如我們再配置 一個Method,用來匹配請求的方法
此時只要請求同時匹配這兩個規則才能夠去訪問對應的服務。?
Gateway Filter Factories?
Filter
Predicate能夠設置一些請求的匹配規則,而Filter則能在請求被目標服務處理前后,添加一些邏輯。例如,我們可以在請求發送到目標服務之前,讓請求新增一個參數。Filter在生效時機上可以分為Post類型和Pre類型,
Pre類型的Filter中定義的邏輯在請求處理前執行,而Post類型的則是在請求處理完成之后,數據返回給用戶之前執行。在生效范圍上,又可以把Filter分為GatewayFilter(作用于單個路由或者同一個分組的路由上,也就是匹配到的id是一樣的)、GlobalFilter(對于每一個路由都生效,也就是每一個請求都生效)。
Gateway Filter Factories(路由過濾工廠)中為我們提供了很多的Filter,例如AddRequestParameter,它能在請求被處理之前在請求中添加一個參數,下面我們來具體使用以下。
Filter和Predicate一樣,也是需要在配置文件中進行配置,具體如下:
server:port: 10030
gateway:routes: # ?關路由配置- id: product-service #路由ID, ?定義, 唯?即可uri: lb://product-service #?標服務地址predicates: #路由條件- Path=/product/**- id: order-serviceuri: lb://order-servicepredicates:- Path=/order/**filters:- AddRequestParameter=userName, bite
這里我們配置了AddRequestParameter,他在請求中添加了一個username字段,值為bite。
下面我們通過一個接口來測試一下是否真的添加了該參數
我們啟動對應的服務來訪問一下這個接口,打印的日志如下:
可以發現成功獲取到Filter添加的參數了。在路由過濾工廠中還有許多其他的Filter,如果大家想了解更多,可以訪問如下地址:
GatewayFilter Factories :: Spring Cloud Gateway
前面我們配置的Filter只能對當前的單一路由生效,如果我們想對所有路由都生效,就需要配置default-Filter,具體配置項如下:
server:port: 10030
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 182.92.242.181:8848gateway:metrics:enabled: trueroutes:- id: order-service #路由規則id, 隨便起, 不重復即可uri: lb://order-service/ #目標服務地址predicates: #路由條件- Path=/order/**- After=2024-03-20T00:00:22.370856700+08:00[Asia/Shanghai]filters:- AddRequestParameter=userName, bite- name: Custom #過濾器名稱args:name: test_custom- id: product-serviceuri: lb://product-service/predicates:- Path=/product/**default-filters:- name: Retryargs:retries: 3statuses: BAD_GATEWAY
?此時配置的Filter就對對所有路徑都生效了。
GlobalFilter
在Gateway中提供了很多全局過濾器(GlobalFilter),用來實現安全監控,日志記錄等功能。常見的有
?? Gateway Metrics Filter: ?關指標,提供監控指標
?? Forward Routing Filter:?于本地forword,請求不轉發到下游服務器
?? LoadBalancer Client Filter: 針對下游服務, 實現負載均衡.
使用GlobalFilter?進行監控等功能需要引入下面這個依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后在配置文件中進行配置,具體配置項如下:
spring:cloud:gateway:metrics:enabled: true #開啟監控相關的全局過濾器
management:endpoints:web:exposure:include: "*"endpoint:health:show-details: alwaysshutdown:enabled: true
此時我們訪問下面這個鏈接就能得到請求的監控信息:
網關地址/actuator
Filter的執行順序
在一個路由下,可能會有多個Filter,他們的執行順序如何呢?我們來看一下。
在請求發送到對應的服務之前,網關會去獲取當前請求需要使用到的所有Filter,并將其按照Order值排序(每個Filter都必須指定一個Order值,Order值越大,執行的順序則越靠前,反之則越靠后,路由過濾工廠給我們提供的Filter都是已經設置好Order值了),根據順序執行Filter。如果Order值一樣,則按照,defaultFilter>GatewayFilter>GlobalFilter的順序執行。