[SpringCloud-Eureka] zookeeper和Eureka使用IP注册

博客主要围绕注册IP而非服务名称展开。使用Eureka和Zookeeper作注册中心时,默认注册主机名,存在解析问题,可通过配置使用IP注册。还对Eureka注册IP进行解读,包括配置注册IP、自定义IP,以及涉及的findFirstNonLoopbackAddress方法。

一.注册IP而不是服务名称

1.1 问题 : 在使用Eureka和Zookeeper作为注册中心的时候,均是默认注册主机名称,但是很多时候主机名称解析会有问题,通过配置使用IP注册:
Eureka:
 eureka.instance.prefer-ip-address = true
Zookeeper:
zookeeper中的配置很隐蔽,查了很久,配置形式如下:
spring.cloud.zookeeper.discovery.instance-host=${spring.cloud.client.ipAddress}
这里右边可以写成IP,但是写成IP不好,比如使用配置中心多实例共享一份配置就有问题,因此写成这样,会
动态获取实例运行的主机的ip。配置后,就可以将IP注册到zookeeper,其他服务使用Feign调用就不会有问题了。

二.Eureka注册IP解读

2.1 配置注册IP
通过eureka.instance.prefer-ip-address = true配置,将微服务的IP注册到Eureka,而不是主机名称
代码解析如下:
在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean类的getHostName方法中:
        @Override
	public String getHostName(boolean refresh) {
		if (refresh && !this.hostInfo.override) {
			this.ipAddress = this.hostInfo.getIpAddress();
			this.hostname = this.hostInfo.getHostname();
		}
		return this.preferIpAddress ? this.ipAddress : this.hostname;
	}
	这里可以看到最后返回时通过preferIpAddress配置项来决定返回的是IP还是主机名称,如下所示,默认是false,
	也就是默认注册的是this.hostname主机名称:
	/**
	 * Flag to say that, when guessing a hostname, the IP address of the server should be
	 * used in prference to the hostname reported by the OS.
	 */
	private boolean preferIpAddress = false;
  • 总言之:eureka.instance.prefer-ip-address = true通过该配置项可以往Eureka注册IP而不是主机名(默认是主机名称);
2.2 配置自定义IP
配置项spring.cloud.client.ipAddress可指定一个IP,如果指定了IP同时开启eureka.instance.prefer-ip-address=true
的话,那么会注册哪一个信息呢?我们跟进if (refresh && !this.hostInfo.override) 这个判断条件,refresh如果为false则
直接走下面的return返回不会再去执行两个get方法(可以理解为不去重新获取,即不refresh刷新),那么条件取决于
HostInfo的override属性,跟进:根据setIpAddress方法我们看到,当设置了eureka.instance.ipAddress时,override
会设置为true,,那么在执行上面的逻辑的时候,就不会再执行hostInfo的getIpAddress和getHostname方法了,因此
就会直接返回this.ipAddress,而这个ipAddress就是spring.cloud.client.ipAddress指定的。
	public void setIpAddress(String ipAddress) {
		this.ipAddress = ipAddress;
		this.hostInfo.override = true;
	}
  • 总言之:配置了eureka.instance.prefer-ip-address = true和spring.cloud.client.ipAddress的情况下,会注册spring.cloud.client.ipAddress指定的IP,而不会通过findFirstNonLoopbackHostInfo方法去寻找本机的非回环地址;
3.findFirstNonLoopbackAddress方法
下面是简单改造过的findFirstNonLoopbackAddress方法,通过该方法可以获取本机的非回环IP地址

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()) {
                    log.trace("Testing interface: " + ifc.getDisplayName());
                    if (ifc.getIndex() < lowest || result == null) {
                        lowest = ifc.getIndex();
                    }
                    else if (result != null) {
                        continue;
                    }

                    // @formatter:off

                        for (Enumeration<InetAddress> addrs = ifc
                                .getInetAddresses(); addrs.hasMoreElements();) {
                            InetAddress address = addrs.nextElement();
                            if (address instanceof Inet4Address
                                    && !address.isLoopbackAddress()
                                   ) {
                                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;
    }
### Spring Cloud EurekaZooKeeper 的服务发现机制对比 #### 功能特性比较 Eureka 是 Netflix 开发的服务发现工具,被广泛应用于微服务体系中。而 ZooKeeper 则是由 Apache 提供的支持可靠协调的技术[^1]。 - **注册中心实现方式** Eureka 使用的是客户端/服务器架构,在这种模式下,所有的节点都需要向一个或多个 Eureka Server 注册自己,并定期发送心跳来更新状态。如果某个实例未能按时发送心跳,则会被认为已经失效并从注册表移除。 相较之下,ZooKeeper 实现了一种更为复杂的分布式一致性协议 Paxos 来管理集群中的领导者选举服务可用性检测等问题。它通过维护一棵文件系统的树形结构来进行资源管理配置同步操作[^2]。 - **数据存储模型** 对于 Eureka 而言,默认情况下会将所有已知的服务实例列表保存在内存里;而对于持久化需求则可以借助外部数据库完成备份恢复等功能扩展。相比之下,ZooKeeper 将其内部的数据表示成节点(znode),这些 znodes 构成了层次化的命名空间用于存储少量元数据信息以及临时性的会话记录等[^3]。 - **容错性高可用性设计** 当涉及到故障转移策略时,两者都提供了相应的解决方案以确保整个系统能够在部分组件发生错误的情况下继续正常运作。不过具体到细节上还是存在差异: - Eureka 支持自我保护机制,即当网络分区事件发生期间允许过期条目暂时保留一段时间而不立即删除,从而减少误判的可能性; - ZooKeeper 需要依赖多数派投票算法选出新的 Leader 成员负责处理写入请求,只有超过半数以上的机器达成一致意见之后才会确认提交成功[^4]。 ```java // Example of registering an application with Eureka client eurekaClient.register(new InstanceInfo.Builder() .setAppName("example-app") .setStatus(Status.UP) .build()); // Example ZK node creation using Curator Framework CuratorFramework zkClient = ...; zkClient.create().creatingParentsIfNeeded().forPath("/services/example", "data".getBytes()); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值