8080端口被占用_Spring Cloud IPv6端口问题排坑

d7202bf3375d10d4a907ffc4654d7862.png

场景

使用 Spring Cloud Eureka 搭建服务注册中心,使用 Zuul 搭建服务网关,一套比较传统的微服务架构。

服务注册中心的地址为 http://localhost:8888,Zuul 网关地址为 http://localhost:8080, 另外搭建一个服务名为 metadata-service 的服务,地址为 http://localhost:8088

问题

metadata-service 中提供一个测试的接口

@RestController
public class MetadataController {
​
    @GetMapping(value = "/test")
    public int getTest() {
        return 1;
    }
}

使用 Postman 进行测试,结果发现直接请求 http://localhost:8088/testmetadata-service 的地址,可以正常得到结果

96681278c2943dec13ecc7c95e898c98.png

而通过网关,使用 Zuul 默认路由规则,调用服务,会出现 404 的错误

3fa5043fe17faba2be200e38c90cf34f.png

分析

首先,我们可以先通过 http://localhost:8888 查看服务是否注册到了服务注册中心

4cc02e713280cc1c0cac837aecd8fc81.png

可以看到没有任何问题。

那么,我们再检查网关有没有获取到 metadata-service 的路由。可以通过 http://localhost:8080/actuator/routes 查看(actuator默认是关闭的,可以通过配置 management.endpoints.web.exposure.include=* 开启)。

534b82dfadd4d40a40b3b77434e36499.png

同样,我们可以看到没有任何问题。

那么,就很奇怪了 ,服务本身没有任何问题,直接调用也可以访问,而通过网关一转发,为什么就 404 了呢?在网上查了一下午,也没有找到有人遇到过类似的问题。。。

问题的关键在我关闭服务后再次请求 http://localhost:8088/test 时终于找到了。正常情况下,关闭了服务后,应该没有返回的 response,但发出请求过后仍然是 404

f6ce84cbf35c65c3b311a515aab49283.png

那么,就很明显了,有另一个进程也在监听 8088 端口 !!!

但还是很奇怪,那为什么服务启动的时候没有报端口被占用的错误呢???

重新启动服务,使用 lsof -i tcp:8088 (Mac OS)查看端口占用情况

ed3ca5e25acdd618fd30c8d9dfa37423.png

果然有两个进程同时在监听,而一个是 IPv4,一个是 IPv6的。

首先,根据这篇文章 https://blog.csdn.net/jiyiqinlovexx/article/details/50959351 的解释,多个进程是完全可以同时监听同一个端口的。

而从 Java 7 开始,默认使用 IPv6 而不是 IPv4 (https://stackoverflow.com/questions/35470838/localhost-vs-127-0-0-1-in-spring-framework),所以对于 Spring 的 localhost 来说,其实真正使用的 IP 地址是 ::1,而不是 127.0.0.1 。使用 Postman 进行测试,可以发现 http://[::1]:8088/test 得到正常结果,而 http://127.0.0.1:8088/test 则为 404 。这就完美地解释了开启服务与停止服务,返回结果不同的问题,Spring 服务所对应的正是那个 IPv6 的进程。

那么,为什么网关转发就到了 IPv4 呢?我们再来看一下服务注册中心里的信息

e50ae09b7f9b6d1e10f1ce68c0756de9.png

可以看到其实 Eureka 保存的是每个服务的 IP 地址是本机的 IPv4 的内网地址,而不是保存域名,这就是问题的关键。我们可以使用 Postman 发送请求 http://localhost:8080/metadata-service/test 后,使用命令 lsof -i tcp:8088 进行验证。

c7b4da63fd96327b0f7ccfef19bd2a8a.png

可以看到的确是向内网 IP 地址,而不是向 localhost 转发请求。

解决方案

至此,问题的原因已经完全清楚了,果然程序都是 debug de 出来的。

最简单的方法也很清楚了,换个端口号就 OK 了。

如果本文有错误或者理解不对的地方,欢迎指正!!!

那么,占了 8088 端口的 IPv4 进程是哪个程序呢?

。。。。Hadoop 出来挨打!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值