HTTP、PHP-FPM、与握手协议

HTTP请求的流程梳理

用户输入url如http:www.baidu.com到浏览器,浏览器如chrom需要将其解析为ip地址才知道需要到哪里去访问哪个服务器。浏览器解析DNS步骤如下

搜索浏览器自身的dns缓存,这个缓存缓存时间短,缓存数目有限。
搜索操作系统的dns缓存
读取host文件的dns映射(一般做本地开发映射都是修改这个文件来达到拦截浏览器请求到本地服务器的目的,从而使本地可以成功映射服务器地址)
先本地网卡配置里的dns服务器发起域名解析请求,这里好像还有一套运营商的处理流程就不在展开了。
下面好像还有一些流程,由于基本不会执行到这一步,一般所以dns运营商的dns服务器都会搞定的。
解析失败,以上任何一步成功都会返回一个成功的ip地址

浏览器以一个随机的端口享这个ip地址的特定端口(默认80)发起著名的TCP3次握手。关于一个http请求是如何到达nginx服务的流程大致如下:
握手完成后的浏览器和服务器就可以愉快地发送http请求了,具体在nginx上流程如下:

PHP-FPM在服务端出来请求中扮演了什么角色

PHP、nginx与CGI协议
对于一个PHP的web程序来说,web服务器(如:nginx)要想与它通信需要通过CGI协议。当一个web请求触达web服务器时,web服务器会创建一个CGI进程,CGI进程将web的请求按照固定的格式进行解析,然后写入标准输入(STDIN)和环境变量中,然后PHP启动的CGI解析器会从标准输入(STDIN)和环境变量中读取http请求的数据,所以$_SERVER才会有数据,然后做出相应的逻辑处理,然后将处理结果放入标准输出(STDOUT),CGI进程从STDOUT中读取响应数据然后传输给浏览器,这样服务端就完成了一次http请求。
上面是CGI的实现流程,但是使用CGI协议的服务器在用户每次访问服务器的时候都需要fork/销毁CGI进程,必然照成多余的系统开销,所以FASTCGI就是为了解决这个问题的。

什么是FastCGI协议
FastCGI会创建一个常驻的master进程和多个worker进程,master进程负责管理和为worker进程反派任务,worker进程负责内部嵌入了CGI解析器用于解释php代码。
PHP-FPM是一个FastCGI进程管理器,在LNMP体系中就是由它来实现FastCGI协议的。同样,它也会创建一个常驻的master进程和多个worker进程,master进程负责监听端口和接收来自nginx的请求,指派任务给worker进程。worker进程的负责解释php代码。PHP-FPM可以通过配置预先启动一定数量的worker进程,这样当http请求触达时就可以更快速的响应。

Nginx关于FastCGI的配置
nginx与PHP-FPM之间的通信一般通过其ngx_http_fastcgi_module模块来实现。其中fastcgi_pass用于设置fastcgi服务器的IP地址;fastcgi_param设置传入fastcgi服务器的参数。这个模块出现的配置问题一般集中在这一块。
相对于并发状态下出现的问题,一般也都集中在fastcgi服务器上,具体表现为fastcgi服务器为了应对大量的http请求必须不停的fork新的worker进程,这时就需要考虑服务器可支持的最大链接数和最大打开文件数(可通过ulimit -n查看)以及php-fpm配置里的最低开启worker数和最高开启worker数的限制。高性能服务器可以在这个方向上调优。

HTTP协议三次握手四次挥手的细节

协议过程中客服端与服务端的状态图

TCP的标志位说明

标志位
英文
说明

SYN
synchronous
建立联机

ACK
acknowledgement
确认

PSH
push
传送

FIN
finish
结束

RST
reset
重置

URG
urgent
紧急

Sequence numbe

顺序号码

Acknowledge number

确认号码

TCP状态说明

状态
说明

LISTEN
侦听状态

SYN_SEND
发送连接请求[SYN=J]后等待匹配连接请求

SYN_RECEIVED
收到连接请求[SYN=J]后发送连接确认包[SYN=k,ack=J+1]后等待收到确认包[Ack=k+1]状态

ESTABLISHED
打开连接后,可以开始传输数据

FIN_WAIT_1
发起连接中断请求[FIN=M]后等待远程TCP确认时[Ack=M+1]状态

FIN_WAIT_2
收到远程中断确认[Ack=M+1]后,等待远程中断请求[FIN=N]

CLOSE_WAIT
收到连接中断请求[FIN=M]后未发送出中断确认包[Ack=M=1]状态

TIME_WAIT
发送确认远程中断请求[Ack=N+1]包后,进入等待状态,用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制

大量TIME_WAIT的原因「常见性能异常」
在四次挥手断开连接中,发起socket主动关闭的一方 socket将进入TIME_WAIT状态,TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),TIME_WAIT状态下的socket不能被回收使用.
具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务.
TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。一般产生的原因是系统没有主动关闭连接,如mysql连接资源没有关闭

关于网络链路中追踪异常用到的运维命令
(以下显示的IP和端口均为假数据)

Linux中查看socket的状态
cat /proc/net/sockstat

参数
说明

sockets:used
已使用的所有协议套接字总量

TCP:inuse
正在使用(正在侦听)的TCP套接字数量。其值≤ netstat –lnt
grep ^tcp
wc –l

TCP:orphan
无主(不属于任何进程)的TCP连接数(无用、待销毁的TCP socket数)

TCP:tw
等待关闭的TCP连接数。其值等于netstat –ant
grep TIME_WAIT
wc –l

TCP:alloc
已分配(已建立、已申请到sk_buff)的TCP套接字数量。其值等于netstat –ant
grep ^tcp
wc –l

TCP:mem
套接字缓冲区使用量

UDP:inuse
正在使用的UDP套接字数量

FRAG
使用的IP段数量

查看当前tcp链接情况
netstat -na | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

参数
说明

LISTEN
正在监听状态

CLOSE_WAIT
对方主动关闭连接或者网络异常导致连接中断,这时我方的状态会变成CLOSE_WAIT 此时我方要调用close()来使得连接正确关闭

ESTABLISHED
建立连接,正在通信

TIME_WAIT
我方主动调用close()断开连接,收到对方确认后状态变为TIME_WAIT

tcp工具抓取网络请求包
tcpdump -n port 3306

mysql 主动断开链接
11:38:45.693382 IP 172.18.0.3.3306 > 172.18.0.5.38822: Flags [F.], seq 123, ack 144, win 227, options [nop,nop,TS val 3000355 ecr 2997359], length 0 # MySQL发送fin包给我11:38:45.740958 IP 172.18.0.5.38822 > 172.18.0.3.3306: Flags [.], ack 124, win 229, options [nop,nop,TS val 3000360 ecr 3000355], length 0 # 我回复ack给它11:38:45.740960 IP 172.18.0.3.3306 > 172.18.0.5.38822: Flags [F.], ack 125, win 231, options [nop,nop,TS val 3000360 ecr 3000355], length 0 # MySQL发送fin包给客户端11:38:45.740965 IP 172.18.0.5.38822 > 172.18.0.3.3306: Flags [.], ack 125, win 229, options [nop,nop,TS val 3000360 ecr 3000355], length 0 # 客户端回复ack给我……
src > dst: flags data-seqno ack window urgent options
# 发生了 3次握手
11:38:15.679863 IP 172.18.0.5.38822 > 172.18.0.3.3306: Flags [S], seq 4065722321, win 29200, options [mss 1460,sackOK,TS val 2997352 ecr 0,nop,wscale 7], length 0
11:38:15.679923 IP 172.18.0.3.3306 > 172.18.0.5.38822: Flags [S.], seq 780487619, ack 4065722322, win 28960, options [mss 1460,sackOK,TS val 2997352 ecr 2997352,nop,wscale 7], length 0
11:38:15.679936 IP 172.18.0.5.38822 > 172.18.0.3.3306: Flags [.], ack 1, win 229, options [nop,nop,TS val 2997352 ecr 2997352], length 0

参数
说明

src > dst
表明从源地址到目的地址

flags
是TCP包中的标志信息,S 是SYN标志, F(FIN), P(PUSH) , R(RST) “.”(没有标记)

data-seqno
是数据包中的数据的顺序号

ack
是下次期望的顺序号

window
是接收缓存的窗口大小

urgent
表明数据包中是否有紧急指针

options
是选项

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理