问题由来:错误的keepalived时间设置 服务端设置了http_keepalived 时间 1s,客户端时间大于server端,客户端反应某些请求没有响应,查看服务日志一些http请求根本没有收到,但是客户端确实记录发送了,只好抓包看在哪里丢弃了
服务端:python+flask+gunicorn 客户端:java
抓包分析:
server端conn到期之后调用了close,且client回应了ack,此时server进入fin_wait2阶段; 之后服务端在此连接上收到了新的http请求,抓包看server直接回应了RST给客户端,强制断开连接,理论上该状态是可以接受数据包的;
代码分析: 在kernel tcp_rcv_state_process func中找到了各个状态收报处理的流程,此时sock应该根本没有RCV_SHUTDOWN,收到fin ack是更新socket SEND_SHUTDOWN;
case TCP_FIN_WAIT2:
/* RFC 793 says to queue data in these states,
* RFC 1122 says we MUST send a reset.
* BSD 4.4 also does reset.
*/
if (sk->sk_shutdown & RCV_SHUTDOWN) {
if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
tcp_reset(sk, skb);
return 1;
}
}
fallthrough;
所以这个RST是什么流程发出来的? 跟应用层有关吗? 又或者是容器的一些特性? 看了一些帖子和试验也有相关的记录,但是根本原因还是不大清楚,欢迎讨论指教!