作者回复: 我对windows不是特别熟,谈下我的理解作为参考: TCP是全双工协议,意思是客户端和服务器都可以发送消息,此时也可以称为你说的完全连接。所谓半开,是指关闭连接时,不要调用close函数,而是调用shutdown,而且传递的参数是关闭写(关闭读不行),这样,相当于四次握手中只发出FIN并收到ACK,此时两端的状态分别是fin_wait2和close_wait,你可以用netstat看到。这种状态下,被动关闭端仍然可以发送消息,而主动关闭端就不行了,这就是半开连接。
作者回复: 问题1和3:内核态与用户态是不一样的,你可以理解为置状态、移队列是原子的(基于自旋锁),要么一起成功,要么一起失败。你可以参看内核的int tcp_v4_rcv(struct sk_buff *skb)函数。 问题2:accept调用后,backlog队列就移除了,nginx调用accept是很及时的。百万并发与backlog无关,backlog只与调用accept是否及时有关
作者回复: 接收完请求后,就会进入writing状态。所以,writing状态不只是处理请求中,发送响应也会在这个状态。所以,writing状态的请求数量通常是最多的。你可以看下137课。
作者回复: 看下CPU的利用率,如果有些CPU满载有些则比较闲,可以考虑多队列网卡;看下网络流量 ,是否到达网卡或者带宽的最大值了?最后再确认下,会不会业务处理上阻塞了Nginx?
作者回复: 原始的pcap文件发我邮箱看下:russelltao@foxmail.com
作者回复: 这种情况不会发生,因为配置文件验证不通过。你可以找下这段源码: if (addr[i].opt.set) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate listen options for %s", addr[i].opt.addr); return NGX_ERROR; }
作者回复: 不是的,listen指定的backlog队列是握手完成的连接,不是半连接SYN队列。你可以看下这个页面:http://man7.org/linux/man-pages/man2/listen.2.html