package com.aps.gateway.config.loadBalancer; 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 lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; @Slf4j @RequiredArgsConstructor @Component public class VersionGrayLoadBalancer implements GrayLoadBalancer { private final DiscoveryClient discoveryClient; private final static String VERSION = "local"; /** * 根据serviceId 筛选可用服务 * @param serviceId 服务ID * @param request 当前请求 * @return ServiceInstance */ @Override public ServiceInstance choose(String serviceId, ServerHttpRequest request) { List instances = discoveryClient.getInstances(serviceId); // 注册中心无实例 抛出异常 if (instances.isEmpty()) { log.warn("No instance available for {}", serviceId); throw new NotFoundException("No instance available for " + serviceId); } // 获取请求version,无则随机返回可用实例 String reqVersion = request.getHeaders().getFirst(VERSION); if (Strings.isBlank(reqVersion)) { return instances.get(RandomUtil.randomInt(instances.size())); } // 遍历可以实例元数据,若匹配则返回此实例 List availableList = instances.stream() .filter(instance -> reqVersion .equalsIgnoreCase(MapUtil.getStr(instance.getMetadata(), VERSION))) .collect(Collectors.toList()); if (CollUtil.isEmpty(availableList)) { return instances.get(RandomUtil.randomInt(instances.size())); } return availableList.get(RandomUtil.randomInt(availableList.size())); } }