Spring Boot RestTemplate调用服务超时/404但Pod内curl正常如何解决
问题根因
- 端口与访问逻辑不匹配:K8s中email-service的Service暴露端口为8080,会自动转发到后端Pod的8088端口,但你的服务通过Consul服务发现直接拉取了Pod的IP+容器端口8088进行访问,跨Pod访问8088端口可能被K8s网络策略拦截,而你在Pod内部执行curl时是访问本地端口,所以不受影响。
- Consul实例更新不及时:你配置的Consul健康检查间隔为20s,已经下线/异常的Pod实例最长需要20s才会被Consul从可用列表中移除,这段时间内请求打到异常实例就会出现连接超时。
- 404报错诱因:部分邮件服务实例的上下文路径配置不一致,或者拼接请求URL时出现重复前缀/缺失前缀的问题,导致端口通但是路径不存在。
解决方案
- 优先使用K8s Service域名访问:直接固定请求地址为
http://email-service:8080,走K8s内置的服务发现与负载均衡,无需通过Consul拉取实例,避免跨Pod端口访问限制和Consul实例异常问题。 - 调整Consul配置(如果必须使用Consul做服务发现):
- 缩短健康检查间隔到3-5s,添加不健康实例摘除配置,加快异常实例下线速度
- 确保Consul注册的服务端口为Service的8080端口而非Pod的8088端口,所有请求统一走Service转发
- 修复代码潜在问题:
- RestTemplate是单例Bean,不要每次调用都执行
restTemplate.setErrorHandler(new ExceptionHandler()),建议在初始化RestTemplate的时候统一配置 - 给RestTemplate添加合理的连接超时、读取超时配置,避免长时间无响应
- 确认所有邮件服务实例的接口路径一致,拼接URL时避免多拼/漏拼路径前缀
- RestTemplate是单例Bean,不要每次调用都执行
- 排查K8s网络策略:确认是否存在NetworkPolicy限制了其他命名空间/服务访问email-service的Pod 8088端口,如果有需要放开对应规则。
内容的提问来源于stack exchange,提问作者Prashant Raghav
相关产品推荐
相关产品推荐

