499是指client在接收到完整响应前断开了链接。iOS端可以通过 task cancel
操作复现。
有以下表现形式:
- Client closed connection before receiving entire response
如果当前请求HTTP/1.1 -
IO: stream cancelled by client
如果请求是HTTP/2.0
Client closed connection before receiving entire response
上面都代表客户端主动断开网络链接。TCP传输层有个FLAGS字段,包含SYN、FIN、ACK、PSH、RST、URG。其中FIN表示端来链接。
这些字段含义为:
SYN:建立连接
FIN:关闭链接
ACK:确认响应
PSH:表示有DATA数据传输
RST:链接重置
考虑到wireshark从网卡读数据,可以看到更详细数据,而charles仅能体现http层数据。所以接下来从TCP层看下499与FIN的关系。
AVPlayerItem fails with -12889 CoreMediaErrorDomain "No response for media file in 4.096s"
这篇文章遇到了和我一样的状况,仅在iOS13或是iOS14才会存在,之前的版本没有这个问题。
后续更新
分析
- 将499业务域名从聚合域名云控去除,经过一天观察499趋势并没有变化,所以排除聚合域名机制问题;
- 前端默认业务域名使用HTTP2.0,LB对业务域名也默认支持HTTP2.0,所以即使走独立域名也仍会走HTTP2.0,HTTP2.0复用TCP导致499无法排除;
- 模拟复现案发现场,后端发现499,但是前端wireshark并没有抓到tcp.flags.fin或是tcp.flags.reset,也就是前端TCP并未断开连接,所以排除前端datatask cancel导致499;
- iOS端可以通过单设备短时间大量请求复现,另外安卓端一些接口,线上也发现单用户短时间大量请求时出现499。另外网上有文章#2分析499有可能是nginx对单设备频繁请求认为不安全然后生成499,所以无法排除Nginx安全设置导致499问题。
- 对特定nginx中配置proxy_ignore_client_abort on,观察发现499问题消失。所以问题基本确认是nginx机制导致。
结论
猜测Nginx出于安全保护机制,将单设备重复请求认为是攻击,然后断开链接,HTTP2.0因为TCP复用机制导致复用的请求都会出现499。
后续跟进
- 上层业务需要对短时间重复请求分析是否合理
- 后端研究婴喜爱Nginx安全机制,是否单设备短时间单个接口大量请求导致误认为攻击,然后断开链接。
网友评论