• Spring Cloud Gateway 扩展支持多版本控制及灰度发布


    第一反应,参考zuul 的实现,自定义断言,然后从上下中获取版本信息即可。但由于 spring cloud gateway 是基于webflux 的反应式编程,所以传统的TTL或者 RequestContextHolder 都不能正确的维护上下文请求。

    先来看 spring clou的 gateway 默认的lb 策略实现 LoadBalancerClientFilter

    public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
        @Override
        public int getOrder() {
            return LOAD_BALANCER_CLIENT_FILTER_ORDER;
        }
    
        @Override
        @SuppressWarnings("Duplicates")
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            return chain.filter(exchange);
        }
    
        protected ServiceInstance choose(ServerWebExchange exchange) {
            return loadBalancer.choose(
                    ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
        }
    }

    我们只需要重写 choose 方法,把上下文请求传递到路由断言中即可,如下

    @Override
    protected ServiceInstance choose(ServerWebExchange exchange) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        return loadBalancer.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(), headers);
    }

    然后在路由断言中通过 PredicateKey获取到即可

    public abstract class AbstractDiscoveryEnabledPredicate extends AbstractServerPredicate {
    
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean apply(@Nullable PredicateKey input) {
            return input != null
                    && input.getServer() instanceof NacosServer
                    && apply((NacosServer) input.getServer(), (HttpHeaders) input.getLoadBalancerKey());
        }
    }

    最后根据版本来计算

        public class GrayMetadataAwarePredicate extends AbstractDiscoveryEnabledPredicate {
    
        @Override
        protected boolean apply(NacosServer server, HttpHeaders headers) {
            PigxRibbonRuleProperties ribbonProperties = SpringContextHolder.getBean(PigxRibbonRuleProperties.class);
    
            if (!ribbonProperties.isGrayEnabled()) {
                log.debug("gray closed,GrayMetadataAwarePredicate return true");
                return true;
            }
    
            final Map<String, String> metadata = server.getMetadata();
            String version = metadata.get(CommonConstants.VERSION);
            // 判断Nacos服务是否有版本标签
            if (StrUtil.isBlank(version)) {
                log.debug("nacos server tag is blank ,GrayMetadataAwarePredicate return true");
                return true;
            }
    
            // 判断请求中是否有版本
            String target = headers.getFirst(CommonConstants.VERSION);
            if (StrUtil.isBlank(target)) {
                log.debug("request headers version is blank,GrayMetadataAwarePredicate return true");
                return true;
            }
    
            log.debug("请求版本:{} ,当前服务版本:{}", target, version);
            return target.equals(version);
        }
    
    }


    参考:https://segmentfault.com/a/1190000019709733?utm_source=tag-newest
  • 相关阅读:
    缅怀
    74LS164的使用
    跑步
    Datasheet,你会读么?[转]
    清华附小给的书单
    iOS-小知识
    网络-GET&POST
    网络-基础
    网络-HTTP其他常见方法
    数据解析
  • 原文地址:https://www.cnblogs.com/duanxz/p/14805775.html
Copyright © 2020-2023  润新知