由来
今天碰到了这个问题,但是最终结果出乎意料
过程
项目相关部分
客户的 OA 对接我们的应用,使用过程中会调用我们的接口,我们的接口再回调客户的回调地址。调用流是:
1 | 客户 OA 后端 ----> 我们应用 A 的后端 -----> 我们应用 B 后端 -----> 客户写的回调地址 |
然后我们接口 A 返回 B 访问回调的报错:
1 | "Get http://10.192.xxx.xxx/xxxxinfo?...: dial tcp 10.192.xxx.xxx:80: connect: cannot assign requested address" |
排查过程
一开始看到这个报错的时候就知道,这个报错是 TCP 四元组哪个组不够用都会报错这个的,但是最优先和最常见的就是 client 的端口耗尽,也就是 client 端的 port range 不够用了,一般是这个 B 服务机器上 client 的端口达到上限了,可以通过下面参数调整下:
1 | sysctl -a |& grep port | grep range |
结果实际上上去 B 服务上 curl 这个 url 能返回 http 状态码。起初以为真的是我们服务 B 在瞬间有端口没释放的 bug,但是 curl 能返回 http 状态码(但是内容是空的),说明 tcp 层面没问题。因为 http 返回信息是空的,我们初步怀疑到是客户的回调服务偷偷更新了后导致的。后面让客户取消掉他们回调 url 的后端校验 token 逻辑。他们换了后还是一样,然后他们把这个接口的逻辑代码截图了,以及把回调服务的日志发过来的。
看了下日志,发现报错信息里有 token 校验过的和没有校验成功的,校验失败的那些原因都是过期了。询问了下发现回调的 IP 后面有好几个服务副本,让客户他们去检查机器时间试试,然后客户下班了,另一个同事说可以单独修改我们服务 B 的设置,指向单台副本绕过负载均衡试试,最后发现 5 个每个单独都正常,指向负载均衡的 IP 就不行,询问后发现是硬件负载均衡。最后第二天客户排查到是硬件负载均衡的连接数异常。是深信服的硬件负载均衡。
结论和学习
其实一开始的 curl 正常能返回 http 状态码就说明 tcp 没问题,不过这次也算是见识到了,server 端的端口不够也会返回 cannot assign requested address
的报错,也就是主动打开还是被动打开,这个错误的信息都是一样的。