Heroku部署Spring Cloud Gateway出现finishConnect连接拒绝500错误
问题根源
核心问题是所有服务的Eureka实例注册了localhost作为访问地址,但Heroku每个服务运行在独立的dyno(容器)中,localhost仅指向当前dyno内部。网关通过Eureka获取服务地址后,尝试访问自身dyno的localhost对应端口,自然触发连接拒绝错误。
具体解决方案
1. 修改Eureka实例注册的地址配置
将Gateway和所有微服务的eureka.instance中的hostname从localhost改为Heroku分配的应用域名,同时保留正确的端口配置:
微服务(patient-service)的application-heroku.yml调整:
eureka: instance: # 移除hostname: localhost hostname: ${HEROKU_APP_NAME}.herokuapp.com nonSecurePort: 80 instance-id: ${spring.application.name}:${random.uuid}
Gateway的application-heroku.yml调整:
eureka: instance: # 移除hostname: localhost hostname: ${HEROKU_APP_NAME}.herokuapp.com nonSecurePort: 80
注:
${HEROKU_APP_NAME}是Heroku自动注入的环境变量,对应你每个服务在Heroku上的应用名称(比如网关的Heroku应用名、patient-service的Heroku应用名)。
2. 优化Eureka服务健康检查(可选但推荐)
Heroku dyno可能会自动重启,添加健康检查配置让Eureka及时更新服务状态,避免无效路由:
在所有服务的配置中添加:
eureka: instance: lease-renewal-interval-in-seconds: 10 lease-expiration-duration-in-seconds: 30 management: endpoints: web: exposure: include: health,info endpoint: health: show-details: always
3. 验证配置效果
部署完成后,访问你的Eureka Server控制台(https://headmed-eureka.herokuapp.com),查看每个服务的Status列,确认显示的是http://<your-app-name>.herokuapp.com:80,而非localhost:xxxx。此时网关即可通过正确的服务地址路由请求。
补充说明
你之前设置nonSecurePort:80是正确的,但因为hostname被设置为localhost,Eureka注册的服务地址依然是localhost:80,网关还是会尝试访问自身dyno的localhost,而非实际的服务dyno,所以无法解决问题。
内容的提问来源于stack exchange,提问作者Dandy

