当前位置: 首页 > Web前端 > HTML5

SpringCloudGateway扩展支持多版本控制和灰度发布

时间:2023-04-05 14:11:48 HTML5

灰度发布什么是灰度发布,请参考概念,我们简单看一下下图,通俗地说:为了保证服务升级顺利process过渡改善了客户体验,一些用户和一些用户会逐步更新,这样多个版本的客户端会同时出现在生产中。为了保证客户端多版本的可用性,需要服务端版本对应多个版本。灰度发布是通过一定的策略保证客户端和服务端多个版本的正确对应。所谓灰度发布,就是当某个服务有多个实例,且实例的版本不一致时,通过nginx+lua(openresty)NetflixZuul的实现方案,只需要自定义ribbon的断言即可,核心是通过TTL获取header中的版本号@Slf4jpublicclassMetadataCanaryRuleHandlerextendsZoneAvoidanceRule{@OverridepublicAbstractServerPredicategetPredicate(){returnnewAbstractServerPredicate(){@Overridepublicbooleanapply(PredicateKeypredicateKey){StringtargetVersion=RibbonVersionHolder.获取上下文();RibbonVersionHolder.clearContext();if(StrUtil.isBlank(targetVersion)){log.debug("客户端没有配置目标版本直接路由");返回真;}DiscoveryEnabledServerserver=(DiscoveryEnabledServer)predicateKey.getServer();finalMapmetadata=server.getInstanceInfo().getMetadata();如果(StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))){log.debug("当前微服务{}没有配置版本直接路由");返回真;}if(metadata.get(SecurityConstants.VERSION).equals(targetVersion)){返回true;}else{log.debug("当前微服务Service{}版本为{},目标版本{}匹配失败",server.getInstanceInfo().getAppName(),metadata.get(SecurityConstants.VERSION),targetVersion);返回假;}}};}}维护请求publicclassRibbonVersionHolder{privatestaticfinalThreadLocalcontext=newTransmittableThreadLocal<>();publicstaticStringgetContext(){returncontext.get();}publicstaticvoidsetContext(Stringvalue){context.set(value);}publicstaticvoidclearContext(){context.remove();}}在SpringCloudGateway中实现第一反应,参考zuul的实现,自定义断言,然后上下获取版本信息但是由于springcloudgateway是基于webflux的响应式编程,无论是传统的TTL还是RequestContextHolder都不能很好的维护context请求。先来看springclou的网关默认的lb策略实现LoadBalancerClientFilterpublicclassLoadBalancerClientFilterimplementsGlobalFilter,Ordered{@OverridepublicintgetOrder(){returnLOAD_BALANCER_CLIENT_FILTER_ORDER;}@Override@SuppressWarnings("Duplicates")publicMonofilter(ServerWebExchangeexchange,GatewayFilterChainchain){returnchain.filter(exchange);}protectedServiceInstancechoose(ServerWebExchangeexchange){returnloadBalancer.choose(((URI)exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());编写choose方法,将上下文请求传给路由断言,如下returnloadBalancer.choose(((URI)exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(),headers);}然后在路由断言中通过PredicateKey获取publicabstractclassAbstractDiscoveryEnabledPredicateex倾向于AbstractServerPredicate{/***{@inheritDoc}*/@Overridepublicbooleanapply(@NullablePredicateKeyinput){returninput!=null&&input.getServer()instanceofNacosServer&&apply((NacosServer)input.getServer(),(HttpHeaders)input.getLoadBalancerKey();}}最后根据版本本来计算if(!ribbonProperties.isGrayEnabled()){log.debug("灰色关闭,GrayMetadataAwarePredicate返回true");返回真;}finalMapmetadata=server.getMetadata();字符串版本=metadata.get(CommonConstants.VERSION);//判断Nacos服务是否有版本标签if(StrUtil.isBlank(version)){log.debug("nacos服务器标签为空,GrayMetadataAwarePredicate返回true");返回真;}//判断请求中是否有版本Stringtarget=headers.getFirst(CommonConstants.VERSION);if(StrUtil.isBlank(target)){log.debug("requestheadersversionisblank,GrayMetadataAwarePredicatereturntrue");返回真;}log.debug("请求版本:{},当前服务版本:{}",target,version);返回target.equals(version);}}集成nacos,动态配置nacos,轻松实现灰度平台QQ:2270033969说说你是如何使用springcloud的。欢迎关注我们,获取更多有趣的JavaEE实践