1.配置指令意义

spring.cloud.inetutils.preferredNetworks[0]=10.10.30.*  //SpringCloud注入注册中心选择的网卡
spring.cloud.zookeeper.discovery.prefer-ip-address=true //使用IP作为注册中心address而不是主机名(默认是主机名称);

2.源码分析

2.1说明:

当maven引入一下spring-cloud-starter-zookeeper-discovery,即:
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>jsr305</artifactId>
                    <groupId>com.google.code.findbugs</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>spring-cloud-netflix-core</artifactId>
                    <groupId>org.springframework.cloud</groupId>
                </exclusion>
            </exclusions>
        </dependency>

就默认开启(当然还有些许,不就一一列举了):
spring.cloud.zookeeper.discovery.register=true //开启网关注册
spring.cloud.zookeeper.discovery.enabled=true //启用zookeeper作为配置中心

2.2 源码

先找到spring-cloud-zookeeper-discovery-*.*.*.jar,如图:

然后打开serviceregister包下ZookeeperServiceRegistryAutoConfiguration.zookeeperDiscoveryProperties(),往下跟进去,可以看到:

	public ZookeeperDiscoveryProperties(InetUtils inetUtils) {
		this.hostInfo = inetUtils.findFirstNonLoopbackHostInfo();//重点在这里,继续跟进去
		this.instanceHost = this.hostInfo.getHostname();
		this.instanceIpAddress = this.hostInfo.getIpAddress();
	}

/*继续跟下去*/

	public HostInfo findFirstNonLoopbackHostInfo() {
		InetAddress address = findFirstNonLoopbackAddress(); //这里也继续跟下去
		if (address != null) {
			return convertAddress(address);
		}
		HostInfo hostInfo = new HostInfo();
		hostInfo.setHostname(this.properties.getDefaultHostname()); //默认localhost 一般是找不到网卡才会设置这个值
		hostInfo.setIpAddress(this.properties.getDefaultIpAddress());//默认127.0.0.1 一般是找不到网卡才会设置这个值
		return hostInfo;
	}

继续跟下去最后来到了核心代码。


	public InetAddress findFirstNonLoopbackAddress() {
		InetAddress result = null;
		try {
			int lowest = Integer.MAX_VALUE;
             /*首先是NetworkInterface.getNetworkInterfaces() 
                这里是获取网卡的意思,一般都是一个网卡集合,
                里面有个 public static native NetworkInterface getAll()
                 获取网卡集合,有兴趣的同学可以研究下这个源码*/
			for (Enumeration<NetworkInterface> nics = NetworkInterface
					.getNetworkInterfaces(); nics.hasMoreElements();) {
				NetworkInterface ifc = nics.nextElement();
                 /*ifc.isUp() 返回网络接口是否已启动并正在运行*/
				if (ifc.isUp()) {
					log.trace("Testing interface: " + ifc.getDisplayName());
					if (ifc.getIndex() < lowest || result == null) {
						lowest = ifc.getIndex();
					}
					else if (result != null) {
						continue;
					}

					// @formatter:off
                    /*ignoreInterface(ifc.getDisplayName()) 是否忽略网卡
                    即执行 spring.cloud.inetutils.ignored-interfaces[0]=eth0 */
					if (!ignoreInterface(ifc.getDisplayName())) {
						for (Enumeration<InetAddress> addrs = ifc
								.getInetAddresses(); addrs.hasMoreElements();) {//开始遍历网卡的接口
							InetAddress address = addrs.nextElement();
                            /*1.address instanceof Inet4Address 只选择ipv4的ip
                              2.address.isLoopbackAddress()用于检查InetAddress是否为回送地                
                              址
                              3. isPreferredAddress(address) 重点讲下这里面的方法们,在下个        
                                 代码块*/
							if (address instanceof Inet4Address
									&& !address.isLoopbackAddress()
									&& isPreferredAddress(address)) {
								log.trace("Found non-loopback interface: "
										+ ifc.getDisplayName());
								result = address;
							}
						}
					}
					// @formatter:on
				}
			}
		}
		catch (IOException ex) {
			log.error("Cannot get first non-loopback address", ex);
		}

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

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

		return null;
	}
	/** For testing. */ boolean isPreferredAddress(InetAddress address) {
        /*isUseOnlySiteLocalInterfaces()只使用站点本地地址,即
        # 遵循 RFC 1918
        # 10/8 前缀
        # 172.16/12 前缀
        # 192.168/16 前缀
        spring.cloud.inetutils.use-only-site-local-interfaces=true 
        一般不会配置走这个的*/
		if (this.properties.isUseOnlySiteLocalInterfaces()) {
			final boolean siteLocalAddress = address.isSiteLocalAddress();
			if (!siteLocalAddress) {
				log.trace("Ignoring address: " + address.getHostAddress());
			}
			return siteLocalAddress;
		}
        /*this.properties.getPreferredNetworks() 指定网卡IP,也就是文章开头的那个注解在这里                    
        实现了,这里就是获取我们配置的IP,并进行有效性匹配
        spring.cloud.inetutils.preferred-networks=192.168.0.1 #可以是IP段:192.168.0.*
        */
		final List<String> preferredNetworks = this.properties.getPreferredNetworks();
		if (preferredNetworks.isEmpty()) {
			return true;
		}
		for (String regex : preferredNetworks) {//进行匹配
			final String hostAddress = address.getHostAddress();
			if (hostAddress.matches(regex) || hostAddress.startsWith(regex)) {
				return true;
			}
		}
		log.trace("Ignoring address: " + address.getHostAddress());
		return false;
	}

 至于 spring.cloud.zookeeper.discovery.prefer-ip-address=true ,是在最初的那个类ZookeeperDiscoveryProperties 实现,即:

	public String getInstanceHost() {
		if (this.preferIpAddress && StringUtils.hasText(this.instanceIpAddress)) {
			return this.instanceIpAddress;
		}
		return this.instanceHost;
	}

3.如何查看

以Linux为例

1.先登录到zookeeper的服务器上,找到zookeeper的bin下面的zkCli.sh文件,并执行它,如图:

2.执行  get 命令,不特定指定的话,SpringCloud注册的服务都是在 /services 下

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐