基于多网卡环境下Eureka服务注册IP的选择问题
作者:取个昵称好难啊Elaine 发布时间:2022-09-16 17:59:15
多网卡环境下Eureka服务注册IP选择
问题场景
服务器上分别配置了eth0和eth1两块网卡,只有eth1的地址可供其它机器访问,在这种情况下,服务注册时Eureka Client会自动选择eth0作为服务ip, 导致其它服务无法调用。
问题原因
由于官方并没有写明Eureka Client探测本机IP的逻辑,所以只能翻阅源代码。Eureka Client的源码在eureka-client模块下,com.netflix.appinfo包下的InstanceInfo类封装了本机信息,其中就包括了IP地址。在
Spring Cloud 环境下,Eureka Client并没有自己实现探测本机IP的逻辑,而是交给Spring的InetUtils工具类的findFirstNonLoopbackAddress()方法完成的:
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
if (!ignoreInterface(ifc.getDisplayName())) { // 是否是被忽略的网卡
for (Enumeration<InetAddress> addrs = ifc
.getInetAddresses(); addrs.hasMoreElements();) {
InetAddress address = addrs.nextElement();
if (address instanceof Inet4Address
&& !address.isLoopbackAddress()
&& !ignoreAddress(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(); // 如果以上逻辑都没有找到合适的网卡,则使用JDK的InetAddress.getLocalhost()
}
catch (UnknownHostException e) {
log.warn("Unable to retrieve localhost");
}
return null;
}
通过源码可以看出,该工具类会获取所有网卡,依次进行遍历,取ip地址合理、索引值最小、已经启动且不在忽略列表的网卡的ip地址作为结果。如果仍然没有找到合适的IP, 那么就将InetAddress.getLocalHost()做为最后的fallback方案。
解决方案
A.忽略指定网卡
spring.cloud.inetutils.gnored-interfaces[0]=eth0 # 忽略eth0, 支持正则表达式
因通过配置application.properties让应用忽略无效的网卡。
B.配置host
当网查遍历逻辑都没有找到合适ip时会走JDK的InetAddress.getLocalHost()。该方法会返回当前主机的hostname, 然后会根据hostname解析出对应的ip。因此第二种方案就是配置本机的hostname和/etc/hosts文件,直接将本机的主机名映射到有效IP地址。
C.手工指定IP
# 指定此实例的ip
eureka.instance.ip-address=
# 注册时使用ip而不是主机名
eureka.instance.prefer-ip-address=true
D.启动时指定IP
java -jar -Dspring.cloud.inetutils.preferred-networks=192.168.20.123
E.禁用eth0
查看网卡的连接信息
[root@localhost ~]# nmcli con sh
NAME UUID TYPE DEVICE
System eth0 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03 802-3-ethernet eth0
禁用eth0
[root@localhost ~]# ifdown eth0
Device 'eth0' successfully disconnected.
启用eth0
[root@localhost ~]# ifup eth0
Eureka中使用IP注册服务
在将微服务放入docker部署在多个云服务器上的时候,发现eureka里显示的是机器名,然后弄了个spring boot admin监控平台,发现它就找不到各个微服务对应的主机了。
在网上查得eureka.instance.prefer-ip-address=true,使用这条配置eureka里显示的就是ip地址了,但是依然不够的,在监控平台里面还是连接不上。
还需要配置instance-和hostname才能使客户端访问到实例
效果应该是这样,点击ip后能访问到相应内容
eureka服务端配置
server.port=8666
spring.application.name=eureka-server
#服务注册中心实例的主机名
eureka.instance.hostname=xxx.xxx.xxx.67
#留存的服务示例低于多少比例进入保护模式
eureka.server.renewal-percent-threshold=0.5
#是否开启保护模式
eureka.server.enable-self-preservation=true
#是否向服务注册中心注册自己
eureka.client.register-with-eureka=false
#是否启用获取服务注册信息,因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,故而设为false
eureka.client.fetch-registry=false
#注册和查询都需要依赖该地址,多个以逗号分隔
eureka.client.serviceUrl.defaultZone=http://admin:password@xxx.xxx.xxx.67:8666/eureka/
#使用ip替代实例名
eureka.instance.prefer-ip-address=true
#设置实例的ID为ip:port
eureka.instance.instance-id=xxx.xxx.xxx.67:${server.port}
#这里使用spring security对注册中心做一个基础的用户名密码登录
security.basic.enabled=true
security.user.name=admin
security.user.password=password
注意到:
eureka.instance.hostname=xxx.xxx.xxx.67
eureka.instance.instance-id=xxx.xxx.xxx.67:${server.port}
这里我直接手工指定了ip,而不是通过${spring.cloud.client.ipAddress}来获取本机的ip,因为使用docker后,发现获取的ip是docker0这张网卡上分配的ip,以172.16.xxx.xxx开头的ip,要使docker绑定外网ip网上也有很多资料,这里先简化操作,就直接手工指定ip了哈。。
客户端配置
eureka.client.service-url.defaultZone=http://admin:password@xxx.xxx.xxx.67:8666/eureka/
eureka.instance.lease-renewal-interval-in-seconds=5
eureka.instance.lease-expiration-duration-in-seconds=10
eureka.client.healthcheck.enable=true
eureka.instance.hostname=xxx.xxx.xxx.67
#设置实例的ID为ip:port
eureka.instance.instance-id=xxx.xxx.xxx.67:${server.port}
注意客户端也要写上eureka.instance.instance-id和eureka.instance.hostname
这样在eureka上就显示的是ip地址了
要使spring boot admin正常工作,还需在spring boot admin上配置
admin服务端配置
spring.application.name=admin-monitor
server.port=7001
#为了安全,以后可以把管理端口设置一下
#management.port=7002
#现在测试环境就关闭了身份认证,真实环境还是需要它的
management.security.enabled=false
客户端配置
#关闭身份认证,以免发生401错误
management.security.enabled=false
#admin监控配置,连接到服务端
spring.boot.admin.url=http://xxx.xxx.xxx.96:7001
#在spring boot admin里以ip的形式注册显示
spring.boot.admin.client.prefer-ip=true
这里比较关键的一步就是在客户端里配置spring.boot.admin.client.prefer-ip=true,这样spring boot admin就能通过ip来访问各个微服务端点,然后收集它们的信息,从而来监控各个微服务了
来源:https://blog.csdn.net/dickysun1987/article/details/83414147
猜你喜欢
- C#中对象,字符串,dataTable、DataReader、DataSet,对象集合转换成Json字符串方法。public class C
- 本文实例讲述了java内部类原理与用法。分享给大家供大家参考,具体如下:概念内部类:可以包含在另外一个类中的类外部类:包含内部类的类每个内部
- 没有阿里云数据库的可以买个最便宜的,我是新用户9.9元买了一个1.买到后点击左上角的工作台2.3. 4. 5.6.7.8
- 本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对各位Java开发者有所帮助
- 前言我们会使用git来保存我们项目的配置文件,但是文件中总有一些敏感数据,对于这些敏感数据我们通常需要给它加密,加密通常有两种加密方式,一种
- 抽象类(abstract):抽象类不能创建实例,它只能作为父类被继承。抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有
- Java continue break 制作简单聊天室程序,屏蔽不文明语言,显示每句话聊天时间package com.swift;impor
- springboot 统一设置时区控制springboot服务的时区为东八区@SpringBootApplicationpublic cla
- 案例:当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Lu
- C# 字符串进制转换/// <summary> /// 进制转换 &nbs
- @Conditional的使用@Conditional可以根据条件来判断是否注入某些Bean。package com.morris.spri
- 下面对Java反射的基础知识进行说明和总结:首先定义一个MyBase类,其中有私有字段,也有公有字段。同时也有公有方法和私有方法。MyBas
- 发现公司集成apollo后原来的@value注入的属性不用做任何变动,也没有换成apollo的注解,遂略看源码后大致了解,做此笔记1、根据文
- 之前学习了设计模式原型模式,在原型模式中就提到了对象的深拷贝。深拷贝指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一
- 本文实例讲述了C#使用iTextSharp从PDF文档获取内容的方法。分享给大家供大家参考。具体实现方法如下:using System;us
- 一、系统介绍1.开发环境开发工具:Eclipse2021JDK版本:jdk1.8Mysql版本:8.0.132.技术选型Java+Swing
- 一、背景上一篇通过Java自带的JConsole来获取zookeeper状态。主要有几个不方便的地方,zk集群一般会部署3或者5台,在多个J
- 概述中国特色社会主义乱码问题是我们经常会碰到的问题,解决的办法有很多,本文分别介绍了GET方式和POST方式中文乱码解决方案中一劳永逸的办法
- 本文实例为大家分享了springboot读取application.yaml文件数据的具体代码,供大家参考,具体内容如下提示:以下是本篇文章
- Filter学习Filter功能拦截jsp、静态图片文件、静态html资源文件实现URL级别的权限访问控制过滤敏感词汇压缩相应信息Filte