一、前因
最近在做公司的一个微服务项目,技术架构为spring cloud + consul + SSM。
当我写完一个功能要在本地测试时,发现服务运行成功,但是前后端联调报500错误。
当时的第一个想法就是gateway服务的问题,但是其他同事却说gateway服务没毛病。
最后想到可能是注册中心的问题,于是访问consul的管理页面。服务是注册上了,但是一眼就能看到毛病:
居然是内网IP!!我惊了!
检查日志信息发现,向注册中心发送注册地址,为内网ip地址:
那么就找到问题原因了。
二、问题
先回想了一下注册中心原理(以前用的是Eruka,不过原理都是大同小异的):
服务提供者启动后,发送自己的信息到注册中心进行注册服务提供者每隔一段时间会想注册中心发送心跳,证明自己还活着,没有挂掉!(默认90s)服务调用者第一次调用服务提供者时,会向注册中心拉取一份服务提供者的地址,并缓存在本地(下次用可以直接从本地取)当服务提供者不可用时,注册中心会将这个服务提供者信息同步到订阅过这个服务的服务消费者。
查阅了一些资料,consul的原理如下图:
和Eruka基本差不多,只是consul不是由服务提供者发送心跳,而是由注册中心访问服务提供者的健康检查链接,以此来判断服务提供者是否还存活!
清晰明了!真正的问题就是:我的服务用局域网链接向consul注册健康检查链接,我能访问consul,但consul肯定是访问不到我的局域网IP来对我服务进行健康检查,因此判断我的服务挂了
因为和其他同事不在一个地方办公,我这里拿到的资料很不全,仅仅只有一个服务的代码和需求文档。连数据库、redis、consul等的地址账号密码,都是自己从项目配置文件中找的。
而他们的办公环境是和公司服务器在一个局域网的,所以他们不会出现我这个问题。
三、解决
因为我本地连接了wifi,需要内网穿透才能将本机暴露出去。
这太麻烦了,所以我将服务打包到了自己的阿里云服务器。
但是,这里也有坑:Consul在不写ip_address配置项的情况下,默认从第一网卡取地址值。而阿里云的第一个网卡就是内网ip。
eth0,eth1,eth2……代表网卡一,网卡二,网卡三……
直接拿服务器的外网