Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VirtualBox(vbox)虚拟网卡和物理网卡同时存在时,sentinel获取ip出错。 #1596

Open
trackercode opened this issue Jul 10, 2020 · 5 comments
Labels
kind/question Category issues related to questions or problems

Comments

@trackercode
Copy link

VirtualBox(vbox)虚拟网卡和物理网卡同时存在时,sentinel获取ip出错,问题细节描述如下:

1.在A主机上运行sentinel;
2.在B主机(物理机)上运行需要被监测流量的应用 app1;
3.在B主机上同时存在物理网卡和虚拟网卡(VirtualBox Host-Only Network),并运行 app1;
4.在A主机sentinel的控制面板(控制台)上获取的机器列表中: 取得的是app1所在主机B的虚拟网卡 VirtualBox Host-Only Network的地址,从而造成监测失败;
5.错误在于sentinel不应该取得B主机虚拟网卡ip, 而应该取得物理网卡ip,因为app1运行在物理机中。

【临时解决方法】:
把虚拟网卡 VirtualBox Host-Only Network 禁用即可,希望大神能从代码层面解决这个问题。据测试VMware的虚拟网卡不会出现类似的问题。

@sczyh30 sczyh30 added the kind/question Category issues related to questions or problems label Jul 15, 2020
@sczyh30
Copy link
Member

sczyh30 commented Jul 15, 2020

Would you like to submit a PR to improve relevant logic?

@ifrozenice
Copy link

确实是这样的,我的服务A运行在docker内,服务注册到nacos上面,nacos显示的就是物理网卡的ip,同时注册到sentinel控制台,sentinel就显示的是虚拟ip。
sentinel获取ip的逻辑在com.alibaba.csp.sentinel.util.HostNameUtil.java里面:

  private static void resolveHost() throws Exception {
        InetAddress addr = InetAddress.getLocalHost();
        hostName = addr.getHostName();
        ip = addr.getHostAddress();
        if (addr.isLoopbackAddress()) {
            // find the first IPv4 Address that not loopback
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface in = interfaces.nextElement();
                Enumeration<InetAddress> addrs = in.getInetAddresses();
                while (addrs.hasMoreElements()) {
                    InetAddress address = addrs.nextElement();
                    if (!address.isLoopbackAddress() && address instanceof Inet4Address) {
                        ip = address.getHostAddress();
                    }
                }
            }
        }
    }

nacos获取ip的的逻辑在org.springframework.cloud.commons.util.InetUtils.java里面:

	public InetAddress findFirstNonLoopbackAddress() {
		InetAddress result = null;
		try {
			int lowest = Integer.MAX_VALUE;
			for (Enumeration<NetworkInterface> nics = NetworkInterface
					.getNetworkInterfaces(); nics.hasMoreElements();) {
				NetworkInterface ifc = nics.nextElement();
				if (ifc.isUp()) {
					this.log.trace("Testing interface: " + ifc.getDisplayName());
					if (ifc.getIndex() < lowest || result == null) {
						lowest = ifc.getIndex();
					}
					else if (result != null) {
						continue;
					}

					// @formatter:off
					if (!ignoreInterface(ifc.getDisplayName())) {
						for (Enumeration<InetAddress> addrs = ifc
								.getInetAddresses(); addrs.hasMoreElements();) {
							InetAddress address = addrs.nextElement();
							if (address instanceof Inet4Address
									&& !address.isLoopbackAddress()
									&& isPreferredAddress(address)) {
								this.log.trace("Found non-loopback interface: "
										+ ifc.getDisplayName());
								result = address;
							}
						}
					}
					// @formatter:on
				}
			}
		}
		catch (IOException ex) {
			this.log.error("Cannot get first non-loopback address", ex);
		}

		if (result != null) {
			return result;
		}

		try {
			return InetAddress.getLocalHost();
		}
		catch (UnknownHostException e) {
			this.log.warn("Unable to retrieve localhost");
		}

		return null;
	}

sentinel能不能也参照nacos的获取ip逻辑优化下?

@sczyh30
Copy link
Member

sczyh30 commented Nov 6, 2020

@ifrozenice Would you like to submit a PR to improve it?

@trackercode
Copy link
Author

trackercode commented Dec 14, 2020

我想从代码层面解决这个错误,但是目前以我的能力还还办不到。

@jasonjoo2010
Copy link
Collaborator

越来越多的关于获取ip的问题。其实这里有一个成本较高但可用的fix可以尝试,那就是做一次当前节点到dashboard汇报节点的路由查找。路由查找成功后(网络能连通的情况下),本端ip即为正确ip。

路由查找的方式,除了获取路由表直接查找,还有一种比较近似的方法,就是尝试创建一下连接,从而拿到本端ip。

获取默认路由的方法(gateway)(直接使用数据报测试1.1.1.1的连通性):

try(DatagramSocket s=new DatagramSocket())
{
    s.connect(InetAddress.getByAddress(new byte[]{1,1,1,1}), 0);
    return NetworkInterface.getByInetAddress(s.getLocalAddress()).getHardwareAddress();
}

更准确的,可以把目标ip更换为dashboard地址。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/question Category issues related to questions or problems
Projects
None yet
Development

No branches or pull requests

4 participants