问题描述
服务方一切正常,客户端在调用的时候却报如下错误:
`
问题分析
根据日志可知,这个问题应该跟https有关系,导致请求服务超时。
因日志打印出来的是 http://app-name/*, 那么客户端是http请求,那是不是服务方提供的是 https 服务呢。
经检查,服务方是一个简单的微服务应用,没有做 https 配置,并且用 https 访问反而报错
由此可得:服务端提供的是http服务,而客户端访问服务方时用了 https
这里吐槽一下 feign 的报错信息:请求报错时,不打印请求的url,却打印一个转换前的伪 url ,增加定位问题的难度
问题跟踪
客户端是使用简单的 feignClient 访问:@FeignClient( name = "app-name" ),并无异常
客户端也没有对程序做过 https 配置,相同配置的其他服务都一切正常,那问题肯定是在调用前,feign修改了请求协议
问题定位
经过代码跟踪,终于在 FeignLoadBalancer 中找到一段代码:
这段代码的功能是拼接用来访问服务端的 url 。引人注目的是,它特意为 https 留下了不小的篇幅。
我们看下 serverIntrospector.isSecure(server) 做了什么
答案揭晓
因为 https 默认的端口是 443,tomcat 默认的SSL服务端口是 8443,因此作者为了图省事,就以服务端口是否以 "443" 结尾来决定服务方提供的是否是 https 服务。不过他也有过犹豫,自嘲地幽了一默:“Can we do better?”
服务端 Docker 实例在启动时被随机分配了某个以 "443" 结尾的主机端口(我遇到的是30443)
客户端在调用时,发现服务方的端口是以 443 结尾,认定服务方是https接口
于是一个 http 服务被当作 https 服务调用,报了文章开头的错误
解决方法
自行实现 ServerIntrospector 接口,并注入到spring容器中
升级 spring-cloud-netflix 包。spring 从 1.4.0.M1 版本开始就修复了这个 bug
领取专属 10元无门槛券
私享最新 技术干货