nginx学习笔记(2)
一、Linux内核参数
Linux系统是通过proc文件系统实现访问内核内部数据结构及改变内核参数的,proc文件系统是一个伪文件系统,通常挂载在/proc目录下,可以通过改变/proc/sys目录下文件中的值对内核参数进行修改。
Linux系统环境下,所有的设备都被看作文件来进行操作,建立的网络连接数同样受限于操作系统的最大打开文件数。最大打开文件数会是系统内存的10%(以KB来计算),称为系统级限制,可以使用sysctl -a | grep fs.file-max命令查看系统级别的最大打开文件数。同时,内核为了不让某个进程消耗掉所有的文件资源,也会对单个进程最大打开文件数做默认值处理,称之为用户级限制,默认值一般是1024,使用ulimit -n命令可以查看用户级文件描述符的最大打开数。
Nginx是一款Web服务器软件,通过系统层面的网络优化可以提升HTTP数据传输的效率。HTTP协议是基于TCP/IP通信协议传递数据的,了解TCP建立连接(三次握手)及进行数据传输的机制是优化网络相关内核参数的基础。
这里对tcp三次握手四次挥手是一种状态说一下我的理解。
三次挥手口述:首先主动打开连接的客户端结束closed阶段,被动打开的服务端也结束closed阶段,进入到listen阶段,随后开始三次握手:
第一次握手:主动开始连接的客户端向服务端发送一段报文:
SYN=1 这表示着想要和服务器端建立连接,这个包名就叫SYN包。
seq=x sequence number 序号,
随之客户端也进入SYN_SENT阶段
第二次握手:服务端在接收到来自客户端的报文之后,也给客户端发送一段报文:
ACK=1 这表示接收到了客户端的请求
SYN=1这表示同意进行数据传送
seq=y 服务端随机生成的序号
这个数据包也叫作ACK—FIN包。
第三次握手:此时客户端在收到了来自服务端的报文之后,已经确定此时服务端到客服端的数据传输没有问题,但此时的服务端并不确认,所以还需要客户端向服务器发送报文。
ACK=1,表示确认接收到了服务端的信息,此时数据数据传输是可靠的。
seq=x+1,
ack=y+1,将客户端发送来的seq=y加1作为自己的返回值。
此时客户端和服务端都进入ESTABLISHED,开始进行数据传送。
四次挥手:
- 第一次挥手:
客户端主动结束ESTABLISHED阶段,向服务器端发送报文:
- seq=w,
- FIN=1,表示客户端主动结束ESTABLISHED阶段。
- 随后客户端进入到FIN_WAIT1阶段
- FIN_WAIT阶段,停止在客户端往服务端的数据传输,但报文正常传输。
- 第二次挥手:
服务端在接受到客户端发送来的请求断开连接的请求后,ESTABLISHED阶段结束,进入到了CLOSE_WAIT半关闭阶段,服务端向客户端回复报文:
- ACK=1,表示接收到客户端发送来的信息。
- seq=v,多次发送数据后到了这个数字。
- ack=u+1,表示收到来自客户端的信息,并将客户端发送来的seq值+1作为自己的返回值。
- 服务端已经接收到了来自客户端断开连接的申请,但是可能数据还没有传输结束,所以还需要一次数据断开的确认。此时客户端也进入到了FIN_WAIT2阶段。
- 第三次挥手:
服务端向客户端发送报文:
- FIN=1,表示已经做好断开数据连接准备。
- ACK=1,表示确认自己数据传输完成。
- seq=w(多次传输结果后的seq数值。)
- ack=u+1。
- 服务端进入到LAST_ACK阶段
- 第四次挥手:
客户端接收到服务端发送来的报文后,由FIN_WAIT2阶段进入到TIME_WAIT阶段。
客户端向服务器发送报文:
- ACK=1,表示确认接收到服务端信息
- ack=w+1,
- seq=u+1,
- 服务端回归CLOSED阶段。
客户端等待完2MSL之后,结束TIME-WAIT阶段,进入CLOSED阶段,由此完成“四次挥手。
l SYN_SENT :这个状态与SYN_RCVD 状态相呼应,当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随即进入到SYN_SENT 状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT 状态表示客户端已发送SYN报文。
2.LISTEN :表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。
3.SYN_RCVD :表示服务器接收到了来自客户端请求连接的SYN报文。在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat很难看到这种状态,除非故意写一个监测程序,将三次TCP握手过程中最后一个ACK报文不予发送。当TCP连接处于此状态时,再收到客户端的ACK报文,它就会进入到ESTABLISHED 状态。
4.ESTABLISHED :表示TCP连接已经成功建立。
5.FIN_WAIT_1 :这个状态得好好解释一下,其实FIN_WAIT_1 和FIN_WAIT_2 两种状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET进入到FIN_WAIT_1 状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2 状态。当然在实际的正常情况下,无论对方处于任何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1 状态一般是比较难见到的,而FIN_WAIT_2 状态有时仍可以用netstat看到。
6.FIN_WAIT_2 :上面已经解释了这种状态的由来,实际上FIN_WAIT_2状态下的SOCKET表示半连接,即有一方调用close()主动要求关闭连接。注意:FIN_WAIT_2 是没有超时的(不像TIME_WAIT 状态),这种状态下如果对方不关闭(不配合完成4次挥手过程),那这个 FIN_WAIT_2 状态将一直保持到系统重启,越来越多的FIN_WAIT_2 状态会导致内核crash。
7.TIME_WAIT :表示收到了对方的FIN报文,并发送出了ACK报文。 TIME_WAIT状态下的TCP连接会等待2*MSL(Max Segment Lifetime,最大分段生存期,指一个TCP报文在Internet上的最长生存时间。每个具体的TCP协议实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟,但BSD传统实现采用了30秒,Linux可以cat /proc/sys/net/ipv4/tcp_fin_timeout看到本机的这个值),然后即可回到CLOSED 可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(这种情况应该就是四次挥手变成三次挥手的那种情况)
-
CLOSING :这种状态在实际情况中应该很少见,属于一种比较罕见的例外状态。正常情况下,当一方发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING 状态表示一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?那就是当双方几乎在同时close()一个SOCKET的话,就出现了双方同时发送FIN报文的情况,这是就会出现CLOSING 状态,表示双方都正在关闭SOCKET连接。
-
CLOSE_WAIT :表示正在等待关闭。怎么理解呢?当对方close()一个SOCKET后发送FIN报文给自己,你的系统毫无疑问地将会回应一个ACK报文给对方,此时TCP连接则进入到CLOSE_WAIT状态。接下来呢,你需要检查自己是否还有数据要发送给对方,如果没有的话,那你也就可以close()这个SOCKET并发送FIN报文给对方,即关闭自己到对方这个方向的连接。有数据的话则看程序的策略,继续发送或丢弃。简单地说,当你处于CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。
-
LAST_ACK :当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态。当收到对方的ACK报文后,也就可以进入到CLOSED 可用状态了。
-
CLOSED:初始状态,表示TCP连接是“关闭着的”或“未打开的”。
理解了以后,下一篇进行安装部署。
以上。