Spring Cloud Gateway 扩展支持多版本控制及灰度发布
灰度发布
什么是灰度发布,概念请参考,我们来简单的通过下图来看下,通俗的讲: 为了保证服务升级过程的平滑过渡提高客户体验,会一部分用户 一部分用户递进更新,这样生产中会同时出现多个版本的客户端,为了保证多个版本客户端的可用需要对应的多个版本的服务端版本。灰度发布就是通过一定策略保证 多个版本客户端、服务端间能够正确对应。
所谓灰度发布,即某个服务存在多个实例时,并且实例版本间的版本并不一致,通过
实现方案
nginx + lua (openresty)
Netflix Zuul
只需要自定义ribbon 的断言即可,核心是通过TTL 获取上下请求header中的版本号
@Slf4j public class MetadataCanaryRuleHandler extends ZoneAvoidanceRule { @Override public AbstractServerPredicate getPredicate() { return new AbstractServerPredicate() { @Override public boolean apply(PredicateKey predicateKey) { String targetVersion = RibbonVersionHolder.getContext(); RibbonVersionHolder.clearContext(); if (StrUtil.isBlank(targetVersion)) { log.debug("客户端未配置目标版本直接路由"); return true; } DiscoveryEnabledServer server = (DiscoveryEnabledServer) predicateKey.getServer(); final Map<String, String> metadata = server.getInstanceInfo().getMetadata(); if (StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))) { log.debug("当前微服务{} 未配置版本直接路由"); return true; } if (metadata.get(SecurityConstants.VERSION).equals(targetVersion)) { return true; } else { log.debug("当前微服务{} 版本为{},目标版本{} 匹配失败", server.getInstanceInfo().getAppName() , metadata.get(SecurityConstants.VERSION), targetVersion); return false; } } }; } }
维护请求中的版本号
public class RibbonVersionHolder { private static final ThreadLocal<String> context = new TransmittableThreadLocal<>(); public static String getContext() { return context.get(); } public static void setContext(String value) { context.set(value); } public static void clearContext() { context.remove(); } }
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); } }
整合nacos
结合nacos的动态配置可以非常方便的实现灰度
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
机器学习在高德搜索建议中的应用优化实践
导读:高德的愿景是:连接真实世界,让出行更美好。为了实现愿景,我们要处理好LBS大数据和用户之间的智能链接。信息检索是其中的关键技术,而搜索建议又是检索服务不可或缺的组成部分。 本文将主要介绍机器学习在高德搜索建议的具体应用,尤其是在模型优化方面进行的一些尝试,这些探索和实践都已历经验证,取得了不错的效果,并且为后来几年个性化、深度学习、向量索引的应用奠定了基础。 对搜索排序模块做重构 搜索建议(suggest服务)是指:用户在输入框输入query的过程中,为用户自动补全query或POI(Point of Interest,兴趣点,地理信息系统中可以是商铺、小区、公交站等地理位置标注信息),罗列出补全后的所有候选项,并进行智能排序。 我们希望通过suggest服务:智能提示,降低用户的输入成本。它的特点是:响应快、不承担复杂query的
- 下一篇
阿里云acp认证考试题库、配套培训视频学习地址
目前阿里云ACP认证考试分为:云计算工程师、大数据分析师和大数据工程师、云安全工程师和云安全行业工程师、人工智能工程师和企业级互联网架构工程师。 如何选择?根据自身特长及未来发展方向;哪个简单?哪个更好考?难吗?询问了几位已通过的同学,给出的答案大多是多看官方文档https://help.aliyun.com/基本没什么问题。所以懂了吗?ACP考试题范围大多集中在官方文档中。 有不少网友都在找阿里云ACP认证的样题,关于阿里云ACP认证考试样题,小编进行了一下搜集。 阿里云ACP考试认证大纲和样题汇总下载地址:下载地址:https://edu.aliyun.com/certification/acp01 关于阿里云ACP认证,目前官网三有配套在线视频课程,这个培训课是单独收费的,可以在官网进行购买,目前价格为900元。有需要的,可以前去购买学习。地址如下: 云计算ACP配套视频课程:https://market.aliyun.com/products/57252001/cmgj029537.html 大数据ACP配套视频课程:https://market.aliyun.com/prod...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果