本文基於 spring cloud gateway 2.0.1 接上文
5、基於路由權重(weigth)的謂詞工廠
Spring Cloud Gateway 提供了基於路由權重的斷言工廠,配置時指定分組和權重值 即可。WeightRoutePredicateFactory 實現了路由權重的功能,按照路由權重選擇 同一個分組中的路由。
spring:
cloud:
gateway:
locator:
enabled: true
routes:
-id: weight_route1
uri: http://www.baidu1.com
order: 6000
predicates:
-Weight= group3, 1
-Path=/ weight/**
filters:
-StripPrefix= 2
-id: weight_route2
uri: http://www.baidu2.com
order: 6000
predicates:
-Path=/ weight/**
-Weight= group3, 9
filters:
-StripPrefix=1
如上配置了兩個對於 / weight/** 路徑轉發的路由定義,這兩個路由是同一個權重分組,且 weight_ route1 權重為 1, weight_ route2 權重為9。 對於10個訪問/ weight/** 路徑的請求來說,將會有9個路由到 weight_ route2,1個路由到 weight_ route1。
5.1、WeightRoutePredicateFactory 權重算法實現過程
weight_ route1: group3, 1
weight_ route2: group3, 9
實現過程為:
1)構造 weights(group3)數組:weights=[ 1, 9]
2)normalize: weights= weights/ sum( weights)=[ 0. 1, 0. 9]
3)計算區間范圍: ranges= weights. collect( 0,( s, w)-> s+ w)=[ 0, 0. 1, 1. 0]
4)生成 隨機數: r= random()
5)搜索隨機數所在的區間: i= integer s. t. r>= ranges[ i]&& r< ranges[ i+ 1]
6)選擇相應的路由: routes[ i]
網關應用服務在啟動時會發布 WeightDefinedEvent,在 WeightCalculatorWebFilter 過濾器中定義了該時間監聽器,當接收到時間 WeightDefinedEvent 時,會自動添加 WeightConfig 到權重配置中。請求在經過 WeightCalculatorWebFilter 時會 生成 一個 隨機數, 根據隨機數所在的區間選擇對應分組的路由。
// WeightRoutePredicateFactory.java
@Override
public Predicate<ServerWebExchange> apply(Config config) {
List<IpSubnetFilterRule> sources = convert(config.sources);
return exchange -> {
InetSocketAddress remoteAddress = config.remoteAddressResolver.resolve(exchange);
if (remoteAddress != null) {
String hostAddress = remoteAddress.getAddress().getHostAddress();
String host = exchange.getRequest().getURI().getHost();
if (log.isDebugEnabled() && !hostAddress.equals(host)) {
log.debug("Remote addresses didn't match " + hostAddress + " != " + host);
}
for (IpSubnetFilterRule source : sources) {
if (source.matches(remoteAddress)) {
return true;
}
}
}
return false;
};
}
當應用到配置的路由斷言 WeightRoutePredicate 時,會根據 ServerWebExchange 中的 WEIGHT_ ATTR 值,判斷當前的 routeId 與對應分組的 routeId 是否一致。