javascript
8080端口被占用_Spring Cloud IPv6端口问题排坑
場景
使用 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/test 即 metadata-service 的地址,可以正常得到結果
而通過網關,使用 Zuul 默認路由規則,調用服務,會出現 404 的錯誤
分析
首先,我們可以先通過 http://localhost:8888 查看服務是否注冊到了服務注冊中心
可以看到沒有任何問題。
那么,我們再檢查網關有沒有獲取到 metadata-service 的路由。可以通過 http://localhost:8080/actuator/routes 查看(actuator默認是關閉的,可以通過配置 management.endpoints.web.exposure.include=* 開啟)。
同樣,我們可以看到沒有任何問題。
那么,就很奇怪了 ,服務本身沒有任何問題,直接調用也可以訪問,而通過網關一轉發,為什么就 404 了呢?在網上查了一下午,也沒有找到有人遇到過類似的問題。。。
問題的關鍵在我關閉服務后再次請求 http://localhost:8088/test 時終于找到了。正常情況下,關閉了服務后,應該沒有返回的 response,但發出請求過后仍然是 404
那么,就很明顯了,有另一個進程也在監聽 8088 端口 !!!
但還是很奇怪,那為什么服務啟動的時候沒有報端口被占用的錯誤呢???
重新啟動服務,使用 lsof -i tcp:8088 (Mac OS)查看端口占用情況
果然有兩個進程同時在監聽,而一個是 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 呢?我們再來看一下服務注冊中心里的信息
可以看到其實 Eureka 保存的是每個服務的 IP 地址是本機的 IPv4 的內網地址,而不是保存域名,這就是問題的關鍵。我們可以使用 Postman 發送請求 http://localhost:8080/metadata-service/test 后,使用命令 lsof -i tcp:8088 進行驗證。
可以看到的確是向內網 IP 地址,而不是向 localhost 轉發請求。
解決方案
至此,問題的原因已經完全清楚了,果然程序都是 debug de 出來的。
最簡單的方法也很清楚了,換個端口號就 OK 了。
如果本文有錯誤或者理解不對的地方,歡迎指正!!!
那么,占了 8088 端口的 IPv4 進程是哪個程序呢?
。。。。Hadoop 出來挨打!!!
總結
以上是生活随笔為你收集整理的8080端口被占用_Spring Cloud IPv6端口问题排坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python微信接口发送消息_Pytho
- 下一篇: java 排序stackoverflow