SpringCloud及Nacos服务注册IP选择问题解决方法
一、SpringCloud以及Nacos服务注册IP选择问题
场景:
微服务部署后,需要相互调用,其中服务A调用服务B时发现无法调用。其中服务注册和发现以及配置中心使用Nacos
分析:
检查了多遍代码后,没有发现调用方式有问题,所以只能是网络问题。通过postman直接调用服务B,发现可以调通,但是使用服务A不行,于是检查服务A在注册中心注册的IP,发现和并不是服务B启动机器的IP。这就是问题所在了。
为什么注册的IP和真实IP不符合呢?原因是Nacos客户端在注册服务时会从机器网卡中选择一个IP来注册,当机器存在多个网卡(例如存在虚拟网卡)时,所选则的IP可能不是真是的物理机的IP,所以,当注册了的是非真实IP后,另一台机器调用时是不可能调通的。
解决:
知道问题后,就要解决,查了一下SpringCloud的官方文档,发现有一项配置如下:
Sometimes, it is useful to ignore certain named network interfaces so that they can be excluded from Service Discovery registration (for example, when running in a Docker container). A list of regular expressions can be set to cause the desired network interfaces to be ignored.
You can also force the use of only specified network addresses by using a list of regular expressions.
spring: cloud: inetutils: preferredNetworks: - 192.168 - 10.0
该项配置用于指定首选IP,当有多个网卡时,指定该IP地址后(支持正则),客户端在选择IP时就会选择符合preferredNetworks配置的IP地址进行注册。
同样的,Nacos也可以配置自己的首选IP以及网卡选择:
spring.cloud.nacos.discovery.ip: spring.cloud.nacos.discovery.networkInterface
我们选择其中一个配置就可以,都能达到相同的效果。
扩展:
虽然问题解决了,但是还是要更深入的了解一下这个IP选择的逻辑。翻了一通源码发现,其大致逻辑如下:
Nacos首先检查有没有ip及networkInterface配置,如果有则使用配置的IP,否则检查networkInterface,并获取IP,如果两者都为空,则使用inetUtils.findFirstNonLoopbackHostInfo().getIpAddress()来获取IP:
而findFirstNonLoopbackHostInfo()的部分逻辑如下:
它最终会返回一个匹配的IPV4地址,并且排除本机回环网络(127.0.0.0-127.255.255.255),并且匹配是否是首选网络(如果配置了preferredNetworks)。
二、注册为指定IP和端口
如果选择固定Ip注册可以配置
spring.cloud.nacos.discovery.ip = 192.168.0.118 spring.cloud.nacos.discovery.port = 9000
如果选择固定网卡配置项
spring.cloud.nacos.discovery.networkInterface = eth0
如果想更丰富的选择,可以使用spring cloud 的工具 InetUtils进行配置
spring.cloud.inetutils.default-hostname
spring.cloud.inetutils.default-ip-address
spring.cloud.inetutils.ignored-interfaces[0]=eth0 # 忽略网卡,eth0
spring.cloud.inetutils.ignored-interfaces=eth.* # 忽略网卡,eth.*,正则表达式
spring.cloud.inetutils.preferred-networks=10.34.12 # 选择符合前缀的IP作为服务注册IP
spring.cloud.inetutils.timeout-seconds
spring.cloud.inetutils.use-only-site-local-interfaces
更多配置
spring.cloud.nacos.discovery.server-addr #Nacos Server 启动监听的ip地址和端口
spring.cloud.nacos.discovery.service #给当前的服务命名
spring.cloud.nacos.discovery.weight #取值范围 1 到 100,数值越大,权重越大
spring.cloud.nacos.discovery.network-interface #当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
spring.cloud.nacos.discovery.ip # 优先级最高
spring.cloud.nacos.discovery.port # 默认情况下不用配置,会自动探测
spring.cloud.nacos.discovery.namespace # 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 spring.cloud.nacos.discovery.access-key # 当要上阿里云时,阿里云上面的一个云账号名
spring.cloud.nacos.discovery.secret-key # 当要上阿里云时,阿里云上面的一个云账号密码
spring.cloud.nacos.discovery.metadata #使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
spring.cloud.nacos.discovery.log-name # 日志文件名
spring.cloud.nacos.discovery.enpoint # 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
ribbon.nacos.enabled # 是否集成Ribbon 默认为true
三、通过内网ip注册为指定外网ip
Nacos注册中心是: https://github.com/alibaba/nacos
各个服务通过Nacos客户端将服务信息注册到Nacos上,当Nacos服务注册的IP默认选择出问题时,可以通过查阅对应的客户端文档,来选择配置不同的IP。
大多公司服务器环境会有两套ip,一套是对内网,一套是对外网。即同一台服务器,有对应两个ip(例:10.0.0.1,100.0.0.1)。
在使用nacos做为注册中心,由于内网环境的因素,A服务注册上去的ip可能是100.0.0.1,B服务注册上去的ip可能是10.0.0.2,经验证10之间调用互通,100之间也互通。但10调用100不同,或者反之也不行。
解决方案:
配置文件加如下配置:
nacos-ip-100.0.0.1 = 10.0.0.1 spring.cloud.nacos.discovery.ip = ${nacos-ip-${spring.cloud.client.ip-address}}
四、Nacos服务注册地址为内网IP的解决办法
问题
最近在使用Spring Cloud Alibaba
这一套微服务解决方案,但是在服务注册的时候,网关死活找不到微服务地址,自己的微服务通过网关怎么也访问不到。
查找原因
仔细一查才发现,网关去访问了一个莫名其妙的IP地址,
去Nacos服务详情去看,果然,我的微服务注册到Nacos的IP地址上也是这个地址,
然后我去我电脑查找这个IP地址,还真有这么一个地址,那么问题来了,Nacos为什么会随意找个本机IP地址然后注册上去?
Nacos服务注册的IP
Nacos注册中心是: https://github.com/alibaba/nacos
各个服务通过Nacos客户端将服务信息注册到Nacos上
当Nacos服务注册的IP默认选择出问题时,可以通过查阅对应的客户端文档,来选择配置不同的网卡或者IP
(参考org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties的配置
)
解决办法
例如,使用了Spring cloud alibaba(官方文档)作为Nacos客户端,
服务默认获取了内网IP 192.168.1.21,
可以通过配置spring.cloud.inetutils.preferred-networks=10.34.12
,使服务获取内网中前缀为10.34.12的IP
如何配置
# 如果选择固定Ip注册可以配置 spring.cloud.nacos.discovery.ip = 10.2.11.11 spring.cloud.nacos.discovery.port = 9090 # 如果选择固定网卡配置项 spring.cloud.nacos.discovery.networkInterface = eth0 # 如果想更丰富的选择,可以使用spring cloud 的工具 InetUtils进行配置 # 具体说明可以自行检索: https://github.com/spring-cloud/spring-cloud-commons/blob/master/docs/src/main/asciidoc/spring-cloud-commons.adoc spring.cloud.inetutils.default-hostname spring.cloud.inetutils.default-ip-address spring.cloud.inetutils.ignored-interfaces[0]=eth0 # 忽略网卡,eth0 spring.cloud.inetutils.ignored-interfaces=eth.* # 忽略网卡,eth.*,正则表达式 spring.cloud.inetutils.preferred-networks=10.34.12 # 选择符合前缀的IP作为服务注册IP spring.cloud.inetutils.timeout-seconds spring.cloud.inetutils.use-only-site-local-interfaces
更多配置
spring.cloud.nacos.discovery.server-addr #Nacos Server 启动监听的ip地址和端口 spring.cloud.nacos.discovery.service #给当前的服务命名 spring.cloud.nacos.discovery.weight #取值范围 1 到 100,数值越大,权重越大 spring.cloud.nacos.discovery.network-interface #当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址 spring.cloud.nacos.discovery.ip # 优先级最高 spring.cloud.nacos.discovery.port # 默认情况下不用配置,会自动探测 spring.cloud.nacos.discovery.namespace # 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 spring.cloud.nacos.discovery.access-key # 当要上阿里云时,阿里云上面的一个云账号名 spring.cloud.nacos.discovery.secret-key # 当要上阿里云时,阿里云上面的一个云账号密码 spring.cloud.nacos.discovery.metadata #使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息 spring.cloud.nacos.discovery.log-name # 日志文件名 spring.cloud.nacos.discovery.enpoint # 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 ribbon.nacos.enabled # 是否集成Ribbon 默认为true
五、较合理的实现方式
1.使用docker进行部署
- 项目打包的时候指定映射后的注册IP和端口或者ip前缀
- 打包进镜像之后运行容器,设置上方指定的端口映射
- 这样也能指定局域网的IP也可以通过docker将相关端口进行映射出来
问题,假如需要映射到公网IP?
2.也可以通过网关进行整改,所有服务都走网关,
- 只需要将网关部署到连接内网服务的网卡上面,将网关的端口进行映射出去供外部调用
- 问题,服务间的调用需要保证注册网络是统一网络
3.通过自定义主机域名,或者本地dns服务,
- 给每个服务指定域名
- 服务注册时候需要将域名进行者注册上去,
问题:可能会更麻烦但是对于网络较为复杂的情况会改善一点劳动量
到此这篇关于SpringCloud以及Nacos服务注册IP选择问题的文章就介绍到这了,更多相关SpringCloud Nacos服务注册内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java中的java.lang.reflect.Type简介
在 Java 中,java.lang.reflect.Type 是一个接口,代表所有类型的通用超类型,它包括原始类型、参数化类型、数组类型、类型变量和基本类型,本文给大家讲解Java中的java.lang.reflect.Type是什么,需要的朋友可以参考下2024-06-06
最新评论