概述
为实现服务和服务之间调用能通过版本号来控制服务调用规则,避免开发人员需要启动所有的服务才能进行业务测试
实现loadbalancer提供的ZoneAvoidanceRule类
public class VersionHandler extends ZoneAvoidanceRule { private static final Logger log = LoggerFactory.getLogger(VersionHandler.class); @Autowired private DiscoveryClient discoveryClient; @Value("${eureka.instance.metadata-map.version:#{null}}") public String version; public VersionHandler() { } public Server choose(Object key) {RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest(); String version =httpServletRequest.getHeader("version"); return getServerByVersion(version,key);} /** * 通过版本号获取服务 * @param version * @param key * @return */ private Server getServerByVersion(String version,Object key){ if(StringUtils.isEmpty(version)){ version = version; } ILoadBalancer lb = this.getLoadBalancer(); List<Server> upList = lb.getReachableServers(); Server server1 = this.getServerByVersion(version, upList); if (null != server1) { log.info("通过版本号version==[{}],获取服务ip==[{}],端口号port==[{}]",version,server1.getHost(),server1.getPort()); return server1; } else { log.info("版本号version==[{}]未获取到对应服务,走轮循",version); Optional<Server> server_opt = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key); return server_opt.isPresent() ? (Server)server_opt.get() : null; } } /** * 过滤服务 * @param version * @param upList * @return */ private Server getServerByVersion(String version, List<Server> upList){ Server server =null; //判断版本号是否配置多个 if (!StringUtils.isEmpty(version) && version.contains(",")){ String[] versions = version.split(","); for (String ver : versions) { server = this.getServer(ver, upList); if (server != null){ break; } } }else { server = this.getServer(version, upList); } return server; } /** * 过滤服务 * @param version * @param upList * @return */ private Server getServer(String version, List<Server> upList) { if (!StringUtils.isEmpty(version) && !CollectionUtils.isEmpty(upList) && upList.size() >= 1) { String[] split = ((Server)upList.get(0)).getMetaInfo().getAppName().split("@"); String appName = split[split.length - 1]; List<ServiceInstance> sis = this.discoveryClient.getInstances(appName); Iterator var6 = upList.iterator(); while(var6.hasNext()) { Server server = (Server)var6.next(); Iterator var8 = sis.iterator(); while(var8.hasNext()) { ServiceInstance si = (ServiceInstance)var8.next(); if (server.getHost().equals(si.getHost()) && server.getPort() == si.getPort() && version.equals(si.getMetadata().get("version"))) { return server; } } } } return null; } }
将自定义的规则注入到spring容器内
@Configuration public class SelfRuleConfig { @Bean public AbstractLoadBalancerRule metadataAwareRule() { return new VersionHandler(); } }
RibbonClient客户端全局设置成自定义的规则
@Configuration @RibbonClients(defaultConfiguration = SelfRuleConfig.class) public class RuleConfig { }
在配置类上配置eureka对应的版本号
eureka.instance.metadata-map.version=system-1