Weight 路由断言工厂需要两个参数:组(group)和权重(int 类型),注意,权重按组计算。语法如下:
Weight=组,权重例如,为 https://weighthigh.org 地址创建两个路由,都放在 group1 分组下,如下:
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2该路由将把 ~80% 的流量转发到 weighthigh.org,把 ~20% 的流量转发到 weighlow.org。
为了验证权重断言,我们需要启动两个订单服务,如下图:

上图中,两个订单服务的端口分别为 8081 和 18081。那么,如何在 IDEA 中启动两个订单服务呢?首先,修改一下 bootstrap.yml 配置文件,支持端口通过 JVM 参数指定,如下:
server:
port: ${port:8081}然后,右键“OrderApplication”选择“Copy Configuration...”复制一个运行配置,如下图:

然后,再次右键新复制的配置,点击“Edit Configuration...”编辑运行配置,添加 VM 参数(端口)等信息,如下图:

将“Gateway 搭建网关服务”项目的配置文件 bootstrap.yml 内容使用如下配置替换:
server:
# 网关端口
port: 9000
spring:
application:
# 服务名称
name: gateway-demo01
cloud:
# nacos
nacos:
discovery:
server-addr: localhost:8848
username: nacos
password: nacos
group: DEFAULT_GROUP
# 网关路由配置
gateway:
# 网关路由配置
routes:
# 路由id,自定义,只要唯一集合
- id: service-order1
# 路由的目标地址,lb 就是负载均衡,后面跟服务名,需要集成 nacos 等服务注册中心
uri: http://localhost:18081
# 路由断言,也就是判断请求是否符合路由规则的条件
predicates:
# Weight断言:根据权重转发请求
- Weight=group1,2
# 路由id,自定义,只要唯一集合
- id: service-order2
# 路由的目标地址,lb 就是负载均衡,后面跟服务名
# 需要集成 nacos 等服务注册中心 lb://service-order
uri: http://localhost:8081
# 路由断言,也就是判断请求是否符合路由规则的条件
predicates:
# Weight断言:根据权重转发请求
- Weight=group1,8上面配置中配置了两个路由,分别是 service-order1 和 service-order2,其中 80% 的请求将发送给 service-order2,20% 的请求将发送给 service-order1。
此时,我们通过 Postman 工具向网关发送 10 次请求,如下图:


从上图可知,有两个请求发送到了 OrderApplication2 服务,有 8 个请求发送到 OrderApplication 服务。
下面是 Weight 路由断言工厂源码:
package org.springframework.cloud.gateway.handler.predicate;
// ...
public class WeightRoutePredicateFactory extends AbstractRoutePredicateFactory<WeightConfig> implements ApplicationEventPublisherAware {
private static final Log log = LogFactory.getLog(WeightRoutePredicateFactory.class);
public static final String GROUP_KEY = WeightConfig.CONFIG_PREFIX + ".group";
public static final String WEIGHT_KEY = WeightConfig.CONFIG_PREFIX + ".weight";
private ApplicationEventPublisher publisher;
public WeightRoutePredicateFactory() {
super(WeightConfig.class);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(GROUP_KEY, WEIGHT_KEY);
}
@Override
public String shortcutFieldPrefix() {
return WeightConfig.CONFIG_PREFIX;
}
@Override
public void beforeApply(WeightConfig config) {
if (publisher != null) {
publisher.publishEvent(new WeightDefinedEvent(this, config));
}
}
@Override
public Predicate<ServerWebExchange> apply(WeightConfig config) {
return exchange -> {
Map<String, String> weights = exchange.getAttributeOrDefault(WEIGHT_ATTR,
Collections.emptyMap());
String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);
// 所有计算和与随机数的比较都在 WeightCalculatorWebFilter 中进行
// all calculations and comparison against random num happened in
// WeightCalculatorWebFilter
String group = config.getGroup();
if (weights.containsKey(group)) {
String chosenRoute = weights.get(group);
if (log.isTraceEnabled()) {
log.trace("in group weight: "+ group + ", current route: " + routeId +", chosen route: " + chosenRoute);
}
return routeId.equals(chosenRoute);
}
return false;
};
}
}