如何配置Spring Gateway实现正确路由?Docker部署Eureka环境路由500错误排查
问题解答
1. 1ee684bc4d4e是什么
这串12位字符是customer服务对应Docker容器的默认主机名。Docker启动容器时如果没有手动指定hostname参数,会默认取容器ID的前12位作为容器内部的主机名,customer服务的Eureka客户端默认采集了这个主机名作为实例地址上报到注册中心。
2. 负载均衡器无法解析的原因
Spring Cloud Gateway从Eureka注册中心获取到的customer服务实例地址就是1ee684bc4d4e这个容器内部主机名,但不同容器默认处于独立的网络命名空间下:
- 没有做特殊网络配置时,Gateway容器的DNS解析列表里没有
1ee684bc4d4e对应的IP映射,自然无法解析到customer服务的实际访问地址,因此抛出UnknownHostException异常。 - 你本地点击Eureka实例跳转404也是同理,你的本地电脑也无法解析这个容器内部的私有主机名。
3. 问题修复方案
可根据你的部署场景选择以下任意一种方案:
方案1:配置Eureka客户端优先用IP注册(最通用,推荐)
修改customer服务的application.yml配置,指定服务注册时优先用IP而非主机名,同时可以显式指定对外暴露的端口:
eureka: instance: prefer-ip-address: true # 开启优先用IP注册 ip-address: 你的Linux服务器公网IP # 容器内部互通可填宿主机内网IP,需要外部访问就填公网IP non-secure-port: 8020 # customer服务对外暴露的端口
修改后重启customer服务即可,此时Eureka注册中心的实例地址会变成IP:8020的格式,Gateway可以正常转发,你本地点击实例也可以正常跳转。
方案2:统一Docker网络+固定容器主机名
如果三个服务都只需要容器内部互通,不需要外部直接访问实例,可以做如下配置:
- 创建自定义Docker网络:
docker network create spring-cloud-net - 启动三个容器时都加入该网络,并且给每个容器设置固定hostname,以customer服务为例:
docker run -d --name customer-service --hostname customer-service --network spring-cloud-net -p 8020:8020 你的customer服务镜像名
Eureka、Gateway容器也用同样的方式加入spring-cloud-net网络,容器之间就可以通过hostname互相解析。
方案3:docker-compose部署优化
如果用docker-compose部署,直接在docker-compose.yml中给每个服务配置hostname,同compose文件下的服务默认处于同一网络,天然支持hostname互解析:
services: customer-service: image: 你的customer镜像 hostname: customer-service ports: - "8020:8020" eureka: image: 你的eureka镜像 hostname: eureka ports: - "8761:8761" gateway: image: 你的gateway镜像 hostname: gateway ports: - "8011:8011"
内容的提问来源于stack exchange,提问作者Tristate
相关产品推荐
相关产品推荐

