文章目錄
- 基本概念
- 執行流程
- 斷言
- 內置路由斷言工廠
- 自定義路由斷言工廠
- 總結
基本概念
路由(Route)是gateway中最基本的組件之一,表示一個具體的路由信息載體。主要定義了下面的幾個信息:
- id:路由標識符,區別于其他Route。
- uri:路由指向的目的地uri,即客戶端請求最終被轉發到的微服務。
- order:用于多個Route之間的排序,數值越小排序越靠前,匹配優先級越高。
- predicate:斷言的作用是進行條件判斷,只有斷言都返回真,才會真正的執行路由。
- filter:過濾器用于修改請求和響應信息。
執行流程
執行流程大體如下:
Gateway Client
向Gateway Server
發送請求;- 請求首先會被
HttpWebHandlerAdapter
進行提取組裝成網關上下文; - 然后網關的上下文會傳遞到
DispatcherHandler
,它負責將請求分發給RoutePredicateHandlerMapping
RoutePredicateHandlerMapping
負責路由查找,并根據路由斷言判斷路由是否可用;- 如果斷言成功,由
FilteringWebHandler
創建過濾器鏈并調用; - 請求會依次經過
PreFilter
->微服務->PostFiter
的方法,最終返回響應;
斷言
Predicate(斷言,謂詞)用于進行條件判斷,只有斷言都返回真,才會真正的執行路由。斷言就是說: 在什么條件下才能進行路由轉發。
內置路由斷言工廠
Spring Cloud Gateway 包括許多內置的斷言工廠,所有這些斷言都與HTTP請求的不同屬性匹配。具體如下:
(1)基于Datetime類型的斷言工廠,此類型的斷言根據時間做判斷,主要有三個:
- AfterRoutePredicateFactory:接收一個日期參數,判斷請求日期是否晚于指定日期;
- BeforeRoutePredicateFactory:接收一個日期參數,判斷請求日期是否早于指定日期;
- BetweenRoutePredicateFactory:接收兩個日期參數,判斷請求日期是否在指定時間段內;
- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
(2)基于遠程地址的斷言工廠 RemoteAddrRoutePredicateFactory:接收一個IP地址段,判斷請求主機地址是否在地址段中
- RemoteAddr=192.168.1.1/24
(3)基于Cookie的斷言工廠 CookieRoutePredicateFactory ,接收兩個參數:cookie名字和一個正則表達式。判斷請求cookie是否具有給定名稱且值與正則表達式匹配。
- Cookie=chocolate, ch.
(4)基于Header的斷言工廠 HeaderRoutePredicateFactory,接收兩個參數:標題名稱和正則表達式。判斷請求Header是否具有給定名稱且值與正則表達式匹配。
- Header=X-Request-ld, \d+
(5)基于Host的斷言工廠 HostRoutePredicateFactory,接收一個參數:主機名模式。判斷請求的Host是否滿足匹配規則。
- Host=**.testhost.org
(6)基于Method請求方法的斷言工廠 MethodRoutePredicateFactory,接收一個參數:判斷請求類型是否跟指定的類型匹配。
- Method=GET
(7)基于Path請求路徑的斷言工廠 PathRoutePredicateFactory,接收一個參數:判斷請求的URI部分是否滿足路徑規則。
- Path=/foo/{segment}
(8)基于Query請求參數的斷言工廠 QueryRoutePredicateFactory,接收兩個參數:請求param和正則表達式,判斷請求參數是否具有給定名稱且值與正則表達式匹配。
- Query=baz, ba.
(9)基于路由權重的斷言工廠 WeightRoutePredicateFactory,接收一個[組名,權重],然后對于同一個組內的路由按照權重轉發
- id: weight_route1uri: host1predicates:- Path=/product/**- Weight=group3, 1
- id: weight_route2uri: host2predicates:- Path=/product/**- Weight=group3, 9
接下來我們驗證幾個內置斷言的使用:
server:port: 7000spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:enabled: true # 讓gateway可以發現nacos中的微服務lowerCaseServiceId: true # 將請求路徑上的服務名配置為小寫routes:- id: shop-product #當前路由標識,要求唯一uri: lb://shop-product #lb代表從nacos中獲取微服務,shop-product是微服務的名稱order: 1 #路由的優先級,數字越小級別越高predicates: #斷言(就是路由轉發要滿足的條件)- Path=/product/** #當請求路徑滿足Path指定的規則時,才進行路由轉發- Before=2019-08-30T15:46:00.000+08:00 #限制請求時間在2019-11-28之前- Method=POST #限制請求方式為postfilters: #過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改- StripPrefix=1 #去掉請求路徑的第一層
自定義路由斷言工廠
我們來設定一個場景:假設我們的應用僅僅讓age在(min,max)之間的人來訪問。
1、在配置文件中,添加一個Age的斷言配置
spring:application:name: api-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848gateway:discovery:locator:enabled: true # 讓gateway可以發現nacos中的微服務lowerCaseServiceId: true # 將請求路徑上的服務名配置為小寫routes:- id: shop-product #當前路由標識,要求唯一uri: lb://shop-product #lb代表從nacos中獲取微服務,shop-product是微服務的名稱order: 1 #路由的優先級,數字越小級別越高predicates: #斷言(就是路由轉發要滿足的條件)- Path=/product/** #當請求路徑滿足Path指定的規則時,才進行路由轉發- Age=18,60 #限制年齡只有在18到60歲之間的人能訪問filters: #過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改- StripPrefix=1 #去掉請求路徑的第一層
2、自定義一個斷言工廠,實現斷言方法
@Component
//泛型用于接收一個配置類,配置類用于接收配置文件中的配置。
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {public AgeRoutePredicateFactory() {super(AgeRoutePredicateFactory.Config.class);}/*** 用于從配置文件中獲取參數值賦值到配置類中的屬性上**/@Overridepublic List<String> shortcutFieldOrder() {//這里的順序要跟配置文件中的參數順序一致return Arrays.asList("minAge","maxAge");}/*** 斷言**/@Overridepublic Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) {return new Predicate<ServerWebExchange>() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {//從 serverWebExchange 獲取傳入的參數String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("age");if(StringUtils.isNotEmpty(ageStr)) {int age = Integer.parseInt(ageStr);return age > config.getMinAge() && age < config.getMaxAge();}return true;}} ;}/*** 自定義一個配置類,用于接收配置文件中的參數**/@Datapublic static class Config {private int minAge;private int maxAge;}}
3、啟動測試
測試發現當age在(18,60)之間可以訪問,其它范圍不能訪問。
總結
到這兒,Gateway 服務網關核心架構的執行流程和斷言就已經介紹完了。下一篇將為大家帶來Gateway 服務網關核心架構的過濾器相關的文章,敬請期待吧!
后續的文章,我們將繼續完善我們的微服務系統,集成更多的Alibaba組件。想要了解更多JAVA后端知識,請點擊文末名片與我交流吧。留下您的一鍵三連,讓我們在這個寒冷的東西互相溫暖吧!