Spring Cloud Gateway(七):路由谓词工厂WeightRoutePredicateFactory

本文基于 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 是否一致。

posted @ 2018-11-25 16:55  IT码客  阅读(2630)  评论(0编辑  收藏  举报