javascript
Spring Cloud Alibaba - 12 使用Nacos的元数据实现金丝雀发布功能
文章目錄
- 需求
- 改造
- 自定義規則
- 全局規則配置
- 配置文件
- 驗證
- 源碼
需求
新功能要上線了 , order-center 存在二個版本 V1(老版本) V2(新版本),product-center也存在二個版本V1(老版本) V2新版本 現在需要做到的是order-center(V1)---->product-center(v1),order-center(V2)---->product-center(v2)。
v2版本是小面積部署的,用來測試用戶對新版本功能的。若用戶完全接受了v2。我們就可以把V1版本卸載完全部署V2版本。
如下調用關系
改造
Spring Cloud Alibaba - 11 Ribbon 自定義負載均衡策略(同集群優先權重負載均衡算法) 在這個基礎上實現該功能
自定義規則
package com.artisan.customrules;import com.alibaba.cloud.nacos.NacosDiscoveryProperties; import com.alibaba.cloud.nacos.ribbon.NacosServer; import com.alibaba.nacos.api.exception.NacosException; import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.BaseLoadBalancer; import com.netflix.loadbalancer.Server; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils;import java.util.ArrayList; import java.util.List;/*** @author 小工匠* @version 1.0* @description: 金絲雀版本權重負載均衡策略* @date 2022/2/3 13:43* @mark: show me the code , change the world*/@Slf4j public class SameClusterPriorityWithVersionRule extends AbstractLoadBalancerRule {@Autowiredprivate NacosDiscoveryProperties discoveryProperties;@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {}@Overridepublic Server choose(Object key) {try {//獲取本地所部署集群的名稱 NJ-CLUSTERString localClusterName = discoveryProperties.getClusterName();//去nacos上獲取和本地 相同集群 相同版本的所有實例信息List<Instance> theSameClusterNameAndTheSameVersionInstList = getTheSameClusterAndTheSameVersionInstances(discoveryProperties);//聲明被調用的實例Instance toBeChooseInstance;//判斷同集群同版本號的微服務實例是否為空if(theSameClusterNameAndTheSameVersionInstList.isEmpty()) {//跨集群調用相同的版本toBeChooseInstance = crossClusterAndTheSameVersionInovke(discoveryProperties);}else {//具有同集群 同版本號的實例toBeChooseInstance = ArtisanWeightedBalancer.chooseInstanceByRandomWeight(theSameClusterNameAndTheSameVersionInstList);log.info("同集群同版本調用--->當前微服務所在集群:{},被調用微服務所在集群:{},當前微服務的版本:{},被調用微服務版本:{},Host:{},Port:{}",localClusterName,toBeChooseInstance.getClusterName(),discoveryProperties.getMetadata().get("current-version"),toBeChooseInstance.getMetadata().get("current-version"),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());}return new NacosServer(toBeChooseInstance);} catch (NacosException e) {log.error("同集群優先權重負載均衡算法選擇異常:{}",e);return null;}}/*** 方法實現說明:獲取相同集群下,相同版本的 所有實例* @author:smlz* @param discoveryProperties nacos的配置* @return: List<Instance>* @exception: NacosException*/private List<Instance> getTheSameClusterAndTheSameVersionInstances(NacosDiscoveryProperties discoveryProperties) throws NacosException {//當前的集群的名稱String currentClusterName = discoveryProperties.getClusterName();//當前的版本號String currentVersion = discoveryProperties.getMetadata().get("current-version");//獲取所有實例的信息(包括不同集群的,不同版本號的)List<Instance> allInstance = getAllInstances(discoveryProperties);List<Instance> theSameClusterNameAndTheSameVersionInstList = new ArrayList<>();//過濾相同集群 同版本號的實例for(Instance instance : allInstance) {if(StringUtils.endsWithIgnoreCase(instance.getClusterName(),currentClusterName)&&StringUtils.endsWithIgnoreCase(instance.getMetadata().get("current-version"),currentVersion)) {theSameClusterNameAndTheSameVersionInstList.add(instance);}}return theSameClusterNameAndTheSameVersionInstList;}/*** 方法實現說明:獲取被調用服務的所有實例* @author:smlz* @param discoveryProperties nacos的配置* @return: List<Instance>* @exception: NacosException*/private List<Instance> getAllInstances(NacosDiscoveryProperties discoveryProperties) throws NacosException {//第1步:獲取一個負載均衡對象BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();//第2步:獲取當前調用的微服務的名稱String invokedSerivceName = baseLoadBalancer.getName();//第3步:獲取nacos clinet的服務注冊發現組件的apiNamingService namingService = discoveryProperties.namingServiceInstance();//第4步:獲取所有的服務實例List<Instance> allInstance = namingService.getAllInstances(invokedSerivceName);return allInstance;}/*** 方法實現說明:跨集群環境下 相同版本的* @author:smlz* @param discoveryProperties* @return: List<Instance>* @exception: NacosException*/private List<Instance> getCrossClusterAndTheSameVersionInstList(NacosDiscoveryProperties discoveryProperties) throws NacosException {//版本號String currentVersion = discoveryProperties.getMetadata().get("current-version");//被調用的所有實例List<Instance> allInstance = getAllInstances(discoveryProperties);List<Instance> crossClusterAndTheSameVersionInstList = new ArrayList<>();//過濾相同版本for(Instance instance : allInstance) {if(StringUtils.endsWithIgnoreCase(instance.getMetadata().get("current-version"),currentVersion)) {crossClusterAndTheSameVersionInstList.add(instance);}}return crossClusterAndTheSameVersionInstList;}private Instance crossClusterAndTheSameVersionInovke(NacosDiscoveryProperties discoveryProperties) throws NacosException {//獲取所有集群下相同版本的實例信息List<Instance> crossClusterAndTheSameVersionInstList = getCrossClusterAndTheSameVersionInstList(discoveryProperties);//當前微服務的版本號String currentVersion = discoveryProperties.getMetadata().get("current-version");//當前微服務的集群名稱String currentClusterName = discoveryProperties.getClusterName();//聲明被調用的實例Instance toBeChooseInstance = null ;//沒有對應相同版本的實例if(crossClusterAndTheSameVersionInstList.isEmpty()) {log.info("跨集群調用找不到對應合適的版本當前版本為:currentVersion:{}",currentVersion);throw new RuntimeException("找不到相同版本的微服務實例");}else {toBeChooseInstance = ArtisanWeightedBalancer.chooseInstanceByRandomWeight(crossClusterAndTheSameVersionInstList);log.info("跨集群同版本調用--->當前微服務所在集群:{},被調用微服務所在集群:{},當前微服務的版本:{},被調用微服務版本:{},Host:{},Port:{}",currentClusterName,toBeChooseInstance.getClusterName(),discoveryProperties.getMetadata().get("current-version"),toBeChooseInstance.getMetadata().get("current-version"),toBeChooseInstance.getIp(),toBeChooseInstance.getPort());}return toBeChooseInstance;} }全局規則配置
@Configuration public class GlobalRibbonConfig {@Beanpublic IRule globalConfig() {// 根據權重的規則// return new ArtisanWeightedRule();// 同集群優先調用規則// return new SameClusterPriorityRule();// 金絲雀版本權重負載均衡策略return new SameClusterPriorityWithVersionRule();} }配置文件
ORDER -------- BeiJingCluster V1 PRODUCT -------- BeiJingCluster V1 PRODUCT -------- BeiJingCluster V2 PRODUCT -------- GuangDongCluster V1 PRODUCT -------- GuangDongCluster V2artisan-cloud-customcfg-ribbon-order工程中Nacos的配置如下:
spring:cloud:nacos:discovery:server-addr: 1.117.97.88:8848cluster-name: BeiJingClustermetadata:current-version: V1application:name: artisan-order-center server:port: 8080服務啟動后
artisan-cloud-customcfg-ribbon-product工程中Nacos的配置如下:
【BeiJingCluster V1】
spring:cloud:nacos:discovery:server-addr: 1.117.97.88:8848cluster-name: BeiJingClustermetadata:current-version: V1application:name: artisan-product-center server:port: 7777【BeiJingCluster V2】
spring:cloud:nacos:discovery:server-addr: 1.117.97.88:8848cluster-name: BeiJingClustermetadata:current-version: V2application:name: artisan-product-center server:port: 7778【GuangDongCluster V1】
spring:cloud:nacos:discovery:server-addr: 1.117.97.88:8848cluster-name: GuangDongClustermetadata:current-version: V1application:name: artisan-product-center server:port: 7779【GuangDongCluster V2】
spring:cloud:nacos:discovery:server-addr: 1.117.97.88:8848cluster-name: GuangDongClustermetadata:current-version: V2application:name: artisan-product-center server:port: 7780驗證
訪問Order提供的接口,
觀察訪問日志
2022-02-03 19:06:32.791 INFO 1856 --- [nio-8080-exec-1] c.a.c.SameClusterPriorityWithVersionRule : 同集群同版本調用--->當前微服務所在集群:BeiJingCluster,被調用微服務所在集群:BeiJingCluster,當前微服務的版本:V1,被調用微服務版本:V1,Host:192.168.5.1,Port:7777再看看Product 7777
測試結果來看order調用product的時候 優先會調用同集群同版本的product提供的服務。
緊接著,我們把同集群的 同版本的product-center下線,那們就會發生跨集群調用相同的版本
再次調用, 觀察日志
2022-02-03 19:10:24.754 INFO 1856 --- [nio-8080-exec-4] c.a.c.SameClusterPriorityWithVersionRule : 跨集群同版本調用--->當前微服務所在集群:BeiJingCluster,被調用微服務所在集群:GuangDongCluster,當前微服務的版本:V1,被調用微服務版本:V1,Host:192.168.5.1,Port:7779說明了當當前集群不存在相同版本的服務時,會跨集群調用相同的版本 。
當我們把Order 也搞個V2 版本
再次調用
觀察日志
源碼
https://github.com/yangshangwei/SpringCloudAlibabMaster/tree/master
總結
以上是生活随笔為你收集整理的Spring Cloud Alibaba - 12 使用Nacos的元数据实现金丝雀发布功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Cloud Alibaba
- 下一篇: Spring Cloud Alibaba