概述
目录
灰度发布
实现方案
nginx + lua (openresty)
Netflix Zuul
Spring Cloud Gateway 中实现
整合nacos
灰度发布
什么是灰度发布,概念请参考,我们来简单的通过下图来看下,通俗的讲: 为了保证服务升级过程的平滑过渡提高客户体验,会一部分用户 一部分用户递进更新,这样生产中会同时出现多个版本的客户端,为了保证多个版本客户端的可用需要对应的多个版本的服务端版本。灰度发布就是通过一定策略保证 多个版本客户端、服务端间能够正确对应。
所谓灰度发布,即某个服务存在多个实例时,并且实例版本间的版本并不一致,通过
实现方案
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的动态配置可以非常方便的实现灰度
原文
●史上最强Tomcat8性能优化
●阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路
●B2B电商平台--ChinaPay银联电子支付功能
●学会Zookeeper分布式锁,让面试官对你刮目相看
●SpringCloud电商秒杀微服务-Redisson分布式锁方案
查看更多好文,进入公众号--撩我--往期精彩
一只 有深度 有灵魂 的公众号0.0
最后
以上就是深情狗为你收集整理的Spring Cloud Gateway 扩展支持多版本控制及灰度发布的全部内容,希望文章能够帮你解决Spring Cloud Gateway 扩展支持多版本控制及灰度发布所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复