欢迎访问Spring Cloud中国社区

我们致力于成为中国最专业的Spring Boot和Spring Cloud交流社区。推荐使用Github直接登录,欢迎加微信号Software_King进入社区微信交流群。若发现网站bug欢迎反馈!

Spring Cloud Gateway中的权重路由

xujin · 2月前 · 979 ·

摘要:本文主要通过运用Spring Cloud Gateway的WeightRoutePredicateFactory对URL进行权重路由。

1.权重路由

1.1 权重路由使用场景

在开发或者测试的时候,或者线上发布,线上服务多版本控制的时候,需要对服务提供权重路由,最常见的使用就是,一个服务有两个版本,旧版本V1,新版本v2。在线上灰度的时候,需要通过网关动态实时推送,路由权重信息。比如95%的流量走服务v1版本,5%的流量走服务v2版本。

issue: The Spring Cloud Gateway issue of Allow Rolling Deployments https://github.com/spring-cloud/spring-cloud-gateway/issues/67

1.2 Spring Cloud Gateway权重路由原理

Spring Cloud Gateway中提供了org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory去实现根据分组设置权重进行路由,因此使用起来相对比较简单,有兴趣的可以debug阅读源码。

  1. public class WeightRoutePredicateFactory extends AbstractRoutePredicateFactory<WeightConfig> implements ApplicationEventPublisherAware {
  2. private static final Log log = LogFactory.getLog(WeightRoutePredicateFactory.class);
  3. public static final String GROUP_KEY = WeightConfig.CONFIG_PREFIX + ".group";
  4. public static final String WEIGHT_KEY = WeightConfig.CONFIG_PREFIX + ".weight";
  5. private ApplicationEventPublisher publisher;
  6. public WeightRoutePredicateFactory() {
  7. super(WeightConfig.class);
  8. }
  9. @Override
  10. public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
  11. this.publisher = publisher;
  12. }
  13. @Override
  14. public List<String> shortcutFieldOrder() {
  15. return Arrays.asList(GROUP_KEY, WEIGHT_KEY);
  16. }
  17. @Override
  18. public String shortcutFieldPrefix() {
  19. return WeightConfig.CONFIG_PREFIX;
  20. }
  21. @Override
  22. public void beforeApply(WeightConfig config) {
  23. if (publisher != null) {
  24. publisher.publishEvent(new WeightDefinedEvent(this, config));
  25. }
  26. }
  27. @Override
  28. public Predicate<ServerWebExchange> apply(WeightConfig config) {
  29. return exchange -> {
  30. Map<String, String> weights = exchange.getAttributeOrDefault(WEIGHT_ATTR,
  31. Collections.emptyMap());
  32. String routeId = exchange.getAttribute(GATEWAY_PREDICATE_ROUTE_ATTR);
  33. // all calculations and comparison against random num happened in
  34. // WeightCalculatorWebFilter
  35. String group = config.getGroup();
  36. if (weights.containsKey(group)) {
  37. String chosenRoute = weights.get(group);
  38. if (log.isTraceEnabled()) {
  39. log.trace("in group weight: "+ group + ", current route: " + routeId +", chosen route: " + chosenRoute);
  40. }
  41. return routeId.equals(chosenRoute);
  42. }
  43. return false;
  44. };
  45. }
  46. }

2.Spring Cloud Gateway中的权重路由案例

2.1 案例代码地址

https://github.com/SoftwareKing/sc-gateway/tree/master/ch4

2.2 Spring Cloud Gateway Server说明

Spring Cloud Gateway will dispatch 95% of the requests to version 1 and 5% of the traffic to version 2 of a specified service, as shown by the following figure.

我们通过在Spring Cloud Gateway中会配置不同的权重信息到不同URL上,Spring Cloud Gateway会根据我们配置的路由权重信息,将请求分发到不同的源服务组,权重信息如ch4/ch4-gateway中的application.yml所示,主要配置信息如下。

  1. spring:
  2. application:
  3. name: ch4-gateway
  4. cloud:
  5. gateway:
  6. routes:
  7. - id: service1_v1
  8. uri: http://localhost:8081/v1
  9. predicates:
  10. - Path=/test
  11. - Weight=service1, 95
  12. - id: service1_v2
  13. uri: http://localhost:8081/v2
  14. predicates:
  15. - Path=/test
  16. - Weight=service1, 5

Weight=service1, 95,Weight=service1, 5就是路由的权重信息。

2.3 源服务

源服务在本案例中源服务如ch4-service-provider所示,主要提提供Gateway Server权重路由对应的后端源服务。因为比较简单因此不做详细说明,主要代码如下所示。

  1. package org.xujin.sc.service;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. import reactor.core.publisher.Mono;
  5. @RestController
  6. public class ServiceController {
  7. @RequestMapping(value = "/v1", produces = "text/plain;charset=UTF-8")
  8. public Mono<String> v1() {
  9. return Mono.just("v1");
  10. }
  11. @RequestMapping(value = "/v2", produces = "text/plain;charset=UTF-8")
  12. public Mono<String> v2() {
  13. return Mono.just("v2");
  14. }
  15. }

2.4 测试

分别启动ch4-gateway,ch4-service-provider进行访问:http://localhost:8080/test 测试,发现会根据所设权重进行路由。

原文链接:http://xujin.org/sc/gw/gw08/