1、遇到的问题
有A,B,C 三个微服务,在服务器s1上部署,我本地开发A微服务和B微服务接口的时候,希望我自己机器的A能调用的我自己机器的B上来,如果我自己没有启动B在调用到S1的B上去。默认情况下我可能调用了多次B 只有一半几率命中到我自己机器,其他的请求都跑到S1去了。
2、解决思路
一般情况我们使用 ribbon 来做负载均衡,也就是说,具体调用哪个微服务是 ribbon 说了算,我们可以自定义ribbon的负载均衡规则来让他优先将请求命中到我自己这台机器上。
3、自定义规则代码
/**
* nacos dev环境微服务调度规则
* 优先同IP,第二同网段
* debugger.local-ip 请配置为本机在nacos上的那个IP
* by 王磊
*/
public class DevNacosDebuggerRuleConfig extends AbstractLoadBalancerRule {
@Value("${debugger.local-ip:}")
private String localIp;
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
/**
* 重写choose方法
*
* @param key
* @return
*/
@SneakyThrows
@Override
public Server choose(Object key) {
//获取负载均衡器
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) getLoadBalancer();
//调用服务的名字
String invokedServerName = baseLoadBalancer.getName();
//获取namingServer(包含nacos注册发现相关api)
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
//获取被调用的服务的所有实例
List<Instance> invokedAllInstanceList = namingService.getAllInstances(invokedServerName);
if (invokedAllInstanceList.isEmpty()) {
throw new RuntimeException(invokedServerName + "找不到服务,请检查服务提供者是否已经启动并且已经注册到nacos中");
}
Instance invokedInstance = null;
String localIp = this.getLocalhostIp();
//192.168.0 获取到同网段ip
String localIpStart = localIp.substring(0, localIp.lastIndexOf("."));
//他的优先级比较高
Instance l1InvokedInstance = null;
for (Instance instance : invokedAllInstanceList) {
if (instance.getIp().equals(localIp)) {
return new NacosServer(instance);
} else if (instance.getIp().startsWith(localIpStart)) {
invokedInstance = instance;
} else if (instance.getIp().equals("192.168.16.229")) {
l1InvokedInstance = instance;
}
}
invokedInstance = l1InvokedInstance == null ? invokedInstance : l1InvokedInstance;
return new NacosServer(invokedInstance != null ? invokedInstance : invokedAllInstanceList.get(0));
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
/**
* 获取本地ip
*
* @return 本机ip
*/
public String getLocalhostIp() {
if (!StringUtils.isEmpty(localIp)) {
return localIp;
}
try {
Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
while (allNetInterfaces.hasMoreElements()) {
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress ip = (InetAddress) addresses.nextElement();
if (ip != null
&& ip instanceof Inet4Address
&& !ip.isLoopbackAddress() //loopback地址即本机地址,IPv4的loopback范围是127.0.0.0 ~ 127.255.255.255
&& ip.getHostAddress().indexOf(":") == -1) {
return ip.getHostAddress();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
4、yml中配置哪些微服务使用此规则
purchase: #purchase 是微服务名字要和nacos里注册的一致
ribbon:
NFLoadBalancerRuleClassName: com.xx.bos.gateway.config.DevNacosDebuggerRuleConfig