0


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选择的逻辑。翻了一通源码发现,其大致逻辑如下:
img
Nacos首先检查有没有ip及networkInterface配置,如果有则使用配置的IP,否则检查networkInterface,并获取IP,如果两者都为空,则使用inetUtils.findFirstNonLoopbackHostInfo().getIpAddress()来获取IP:

img

而findFirstNonLoopbackHostInfo()的部分逻辑如下:

img

它最终会返回一个匹配的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.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服务,- 给每个服务指定域名- 服务注册时候需要将域名进行者注册上去, - 问题:可能会更麻烦但是对于网络较为复杂的情况会改善一点劳动量
标签: spring cloud

本文转载自: https://blog.csdn.net/weixin_48359973/article/details/132378494
版权归原作者 算了吧,你不配 所有, 如有侵权,请联系我们删除。

“SpringCloud以及Nacos服务注册IP选择问题”的评论:

还没有评论