zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Python全栈开发之---mysql数据库
    python爬虫项目(scrapy-redis分布式爬取房天下租房信息)
    python多线程爬虫+批量下载斗图啦图片项目(关注、持续更新)
    python爬虫+数据可视化项目(关注、持续更新)
    超融合基本架构简单定义
    开启新生之路,,,学习网络
    Redhat7.2 ----team网卡绑定
    设计原则
    java应用程序的运行机制
    java三大版本和核心优势
  • 原文地址:https://www.cnblogs.com/duanxz/p/14805775.html
Copyright © 2011-2022 走看看