From 240b112ac361412b74574c0842d84448085ead1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A1=E5=B0=94?= Date: Wed, 1 Jun 2022 21:23:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20'pigx-common/pigx-common-g?= =?UTF-8?q?ateway/src/main/java/com/pig4cloud/pigx/common/gateway/rule/Ver?= =?UTF-8?q?sionGrayLoadBalancer.java'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加灰度路由支持nacos权重分配获取服务实例的功能 1.修复原灰度路由存在的一个bug: 原逻辑会返回带有版本号的服务实例,这些带版本号的服务按照道理应该暂时不提供公测功能 2.增加了一个功能:支持原nacos提供的权重功能 --- .../gateway/rule/VersionGrayLoadBalancer.java | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/rule/VersionGrayLoadBalancer.java b/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/rule/VersionGrayLoadBalancer.java index 6c42fc9a8..45c152e21 100644 --- a/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/rule/VersionGrayLoadBalancer.java +++ b/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/rule/VersionGrayLoadBalancer.java @@ -19,8 +19,9 @@ package com.pig4cloud.pigx.common.gateway.rule; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.text.CharSequenceUtil; +import com.alibaba.nacos.client.naming.utils.Chooser; +import com.alibaba.nacos.client.naming.utils.Pair; import com.pig4cloud.pigx.common.core.constant.CommonConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,7 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.http.server.reactive.ServerHttpRequest; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -36,7 +38,7 @@ import java.util.stream.Collectors; * @author lengleng * @date 2020/1/12 *

- * 基于客户端版本号灰度路由 + * 基于客户端版本号灰度路由,增加基于nacos权重获取服务 */ @Slf4j @RequiredArgsConstructor @@ -48,36 +50,61 @@ public class VersionGrayLoadBalancer implements GrayLoadBalancer { * 根据serviceId 筛选可用服务 * @param serviceId 服务ID * @param request 当前请求 - * @return + * @return 服务实例:ServiceInstance */ @Override public ServiceInstance choose(String serviceId, ServerHttpRequest request) { List instances = discoveryClient.getInstances(serviceId); - // 注册中心无实例 抛出异常 if (CollUtil.isEmpty(instances)) { log.warn("No instance available for {}", serviceId); throw new NotFoundException("No instance available for " + serviceId); } - // 获取请求version,无则随机返回可用实例 String reqVersion = request.getHeaders().getFirst(CommonConstants.VERSION); - if (StrUtil.isBlank(reqVersion)) { - return instances.get(RandomUtil.randomInt(instances.size())); + if (CharSequenceUtil.isBlank(reqVersion)) { + //过滤出不含VERSION实例 + List versionInstanceList = instances.stream() + .filter(instance -> !instance.getMetadata().containsKey(CommonConstants.VERSION)) + .collect(Collectors.toList()); + if(CollUtil.isEmpty(versionInstanceList)){ + //根据权重获取实例 + return randomByWeight(instances); + } + //根据权重获取实例 + return randomByWeight(versionInstanceList); } - // 遍历可以实例元数据,若匹配则返回此实例 List availableList = instances.stream() .filter(instance -> reqVersion .equalsIgnoreCase(MapUtil.getStr(instance.getMetadata(), CommonConstants.VERSION))) .collect(Collectors.toList()); - if (CollUtil.isEmpty(availableList)) { - return instances.get(RandomUtil.randomInt(instances.size())); + //根据权重获取实例 + return randomByWeight(instances); } + //根据权重获取实例 + return randomByWeight(availableList); + } - return availableList.get(RandomUtil.randomInt(availableList.size())); - + /** + * 根据nacos设置的权重返回实例 + * @param serviceInstances 服务实例集合 + * @return 服务实例:ServiceInstance + */ + protected ServiceInstance randomByWeight(final List serviceInstances){ + if(serviceInstances.size()==1){ + return serviceInstances.get(0); + }else { + List> hostsWithWeight = new ArrayList<>(); + for (ServiceInstance serviceInstance : serviceInstances) { + if ("true".equals(serviceInstance.getMetadata().getOrDefault("nacos.healthy","true"))) { + hostsWithWeight.add(new Pair<>(serviceInstance, Double.parseDouble(serviceInstance.getMetadata().getOrDefault("nacos.weight","1")))); + } + } + Chooser vipChooser = new Chooser<>("www.taobao.com",hostsWithWeight); + return vipChooser.randomWithWeight(); + } } }