Spring Cloud Gateway实现灰度发布方案

  @Slf4j

  @Component

  public class GrayReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {

  private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;

  private final LoadBalancerClientFactory clientFactory;

  public GrayReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory) {

  this.clientFactory = clientFactory;

  }

  @Override

  public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

  URI url = (URI) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);

  String schemePrefix = (String) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);

  if (url != null && ("grayLb".equals(url.getScheme()) || "grayLb".equals(schemePrefix))) {

  ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);

  if (log.isTraceEnabled()) {

  log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);

  }

  return this.choose(exchange).doOnNext((response) -> {

  if (!response.hasServer()) {

  throw NotFoundException.create(true, "Unable to find instance for " + url.getHost());

  } else {

  URI uri = exchange.getRequest().getURI();

  String overrideScheme = null;

  if (schemePrefix != null) {

  overrideScheme = url.getScheme();

  }

  DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance((ServiceInstance) response.getServer(), overrideScheme);

  URI requestUrl = this.reconstructURI(serviceInstance, uri);

  if (log.isTraceEnabled()) {

  log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);

  }

  exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);

  }

  }).then(chain.filter(exchange));

  } else {

  return chain.filter(exchange);

  }

  }

  private Mono> choose(ServerWebExchange exchange) {

  URI uri = (URI) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);

  GrayRoundRobinLoadBalancer loadBalancer = new GrayRoundRobinLoadBalancer(clientFactory.getLazyProvider(uri.getHost(), ServiceInstanceListSupplier.class), uri.getHost());

  return loadBalancer.choose(this.createRequest(exchange));

  }

  private Request createRequest(ServerWebExchange exchange) {

  HttpHeaders headers = exchange.getRequest().getHeaders();

  return new DefaultRequest<>(headers);

  }

  protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {

  return LoadBalancerUriTools.reconstructURI(serviceInstance, original);

  }

  @Override

  public int getOrder() {

  return LOAD_BALANCER_CLIENT_FILTER_ORDER;

  }

  }