线上问题-ERR_CONNECTION_CLOSED
例行周四的技术会议时,有人抛出了一个线上故障,Web上有个表格表头过滤,当选择所有值请求时会报错
ERR_CONNECTION_CLOSED
,但当选择较少的时正常返回200。因为不清楚ERR_CONNECTION_CLOSED
的含义,因此排查过程也走了点弯路,这里总结下。
ERR_CONNECTION_CLOSED
Chrome下请求报错但没有状态码,因此一开始并不确定是服务端还是浏览器层面报错。
但一般还是从前端排查起。
request body limit?
现象上来看,参数值减少即返回200,参数值较多就会报错,因此一开始判断可能是请求body体的大小限制。
因此随便构造了较长的数组参数,进行请求发现后端正常返回信息,当然只是会报非法参数错误,因此推翻是body大小限制。
header length limit?
注意到报错时还有个特征是request header中会传递当前URL,而表格表头过滤操作时,URL也会更新,因此可能是header长度问题。
报错时,请求头大概有10KB,为了印证这一点,自定义一个header字段,填充值,使得长度达到10KB,同时选择一个之前正常返回200的值进行测试,发现还是报错了。
因此可以确定并非某个参数值在业务层面导致的报错,而是request header长度限制导致。
解决
原因一旦找到,解决办法也就明确
增加容器header长度限制
- HTTP本身对于req.header长度并没限制,只是各个容器有限制
修改请求头,考虑避免传递过大请求头问题,比如这里是传递了较长的URL作为header的参数,只是为了作为日志记录,因此完全可以没必要传递完整URL参,因此这里最终决定采用截取方案,即限制最长URL,同时需要注意过长URL本身就不合理,因为浏览器对于URL也存在长度的限制
需要知道,这里是因为header长度限制报错导致,但如果body长度超过,也会出现该错。
回过头来,再去看报错信息ERR_CONNECTION_CLOSED,也就明白了
HTTP连接是建立在TCP连接之上,如上当header长度超过后,服务器直接关闭了该TCP链接,而平时所谓的500,400只是HTTP连接结束,但TCP连接还存在,两者还是有根本的不同。
既然是链接,因此请求一定是正常发送到了服务端,只是在服务端容器那层因为长度限制超过而报错了。
node/–max-http-header-size
问题解决了,为了强化理解,这里以node为例,来复现下问题
node对于header大小限制默认是8KB,于是这里增加较大的自定义header项,请求node服务端,发现请求报错。重启启动node,同时指定header上限为1500000,发现返回200。
1 | // 启动服务端 |
总结
一般而言习惯根据Response Status来判断后端错误,但是比如上述报错并没有status,但确实是服务端报错。
因此需要有这样认知,服务端报错并不一定有responseStaus