HTTP、PHP-FPM、與握手協議

HTTP請求的流程梳理

  1. 用戶輸入url如http:www.baidu.com到瀏覽器,瀏覽器如chrom須要將其解析爲ip地址才知道須要到哪裏去訪問哪一個服務器。瀏覽器解析DNS步驟以下php

    1. 搜索瀏覽器自身的dns緩存,這個緩存緩存時間短,緩存數目有限。
    2. 搜索操做系統的dns緩存
    3. 讀取host文件的dns映射(通常作本地開發映射都是修改這個文件來達到攔截瀏覽器請求到本地服務器的目的,從而使本地能夠成功映射服務器地址)
    4. 先本地網卡配置裏的dns服務器發起域名解析請求,這裏好像還有一套運營商的處理流程就不在展開了。
    5. 下面好像還有一些流程,因爲基本不會執行到這一步,通常因此dns運營商的dns服務器都會搞定的。
    6. 解析失敗,以上任何一步成功都會返回一個成功的ip地址
  1. 瀏覽器以一個隨機的端口享這個ip地址的特定端口(默認80)發起著名的TCP3次握手。關於一個http請求是如何到達nginx服務的流程大體以下:
  2. 握手完成後的瀏覽器和服務器就能夠愉快地發送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請求。mysql

上面是CGI的實現流程,可是使用CGI協議的服務器在用戶每次訪問服務器的時候都須要fork/銷燬CGI進程,必然照成多餘的系統開銷,因此FASTCGI就是爲了解決這個問題的。nginx

什麼是FastCGI協議

FastCGI會建立一個常駐的master進程和多個worker進程,master進程負責管理和爲worker進程反派任務,worker進程負責內部嵌入了CGI解析器用於解釋php代碼。web

PHP-FPM是一個FastCGI進程管理器,在LNMP體系中就是由它來實現FastCGI協議的。一樣,它也會建立一個常駐的master進程和多個worker進程,master進程負責監聽端口和接收來自nginx的請求,指派任務給worker進程。worker進程的負責解釋php代碼。PHP-FPM能夠經過配置預先啓動必定數量的worker進程,這樣當http請求觸達時就能夠更快速的響應。sql

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 是選項

傳送門

相關文章
相關標籤/搜索