【PHP7源碼學習】2019-04-09 FastCGI協議1

baiyanphp

所有視頻:https://segmentfault.com/a/11...html

計算機網絡架構的分層與封裝

  • 咱們常常談到,計算機網絡有多種體系架構,如OSI七層模型、TCP/IP四層模型等等。那麼,爲何要將計算機網絡分紅這麼多層呢?並且,每一層都要加上其特有的頭部(如TCP頭部、IP頭部等等)進行封裝,這樣設計的緣由又何在?
  • 首先咱們看一個咱們常常看到的C/S架構數據流動過程圖:

  • 咱們以TCP/IP四層網絡體系架構爲例,總結一下各層服務的做用:
  • 應用層:用戶直接可以操做的層,處理應用程序的邏輯,在用戶空間實現
  • 傳輸層:爲兩臺計算機上的應用程序提供端到端的通訊,實現了數據通過網絡層到達計算機後可以分發到各個端口(分用),在內核空間實現
  • 網絡層:提供精確到兩端計算機互聯網IP地址的通訊,實現了數據包在互聯網上的選路與轉發,在內核空間實現
  • 數據鏈路層:提供基於物理媒介(如網卡)的數據傳輸服務,在內核空間實現
  • 首先談談爲何要分層。在咱們實際的項目開發過程當中,咱們經常提到的模塊化、服務化,其實和計算機網絡爲何要分層的原理相似。咱們能夠將每一層都當作一個模塊、一個服務,其內部的實現細節對於上一層或者下一層都是隱藏的,可能只對外暴露一些API而已。若是上層要使用下層提供的服務,根本不須要關注下一層內部的實現細節,只需使用下層提供的API便可。這樣一來,方便了開發與維護,進而提升了計算機網絡總體的運做效率。
  • 咱們再談爲何要封裝。剛纔咱們談到了每一個模塊都是獨立的。上層爲了使用下層提供的服務,必須封裝。舉個例子,應用層想使用傳輸層提供的端到端的數據傳輸服務,那麼傳輸層就會將應用層下發的數據先存起來。爲了實現端到端的數據傳輸,傳輸層模塊內部須要標識雙方的端口號。因此,它就會將端口號還有一些額外的信息(被稱做(TCP/UDP)首部),和應用層下發的數據部分進行封裝,一塊兒傳給下一層(即網絡層)。這樣,經過封裝每一層特有的頭部,實現了每一層獨特的功能,最終實現了精確到端口號的端到端數據傳輸服務。

爲何須要FastCGI協議

  • 在LNMP架構中,客戶端瀏覽器與nginx代理是經過HTTP協議進行通訊的。在請求到達nginx以後,數據最終會被轉發給上游的PHP-FPM。它們之間的通訊,屬於同一機器上、不一樣端口號之間的通訊。FastCGI協議同HTTP協議同樣,是基於TCP協議的,處於TCP協議的上層。而 TCP協議傳輸的僅僅是無心義的字節流數據,接收方並不能正確讀取數據的含義。因此,它們也須要一個相似於HTTP的協議的、一種格式或語法上的規範與約定。這樣一來,通訊雙方纔可以更好地理解、解析並正確讀取對方傳輸的信息以及數據,理解數據發送方所表達的含義,這就是FastCGI協議開發的目的所在。

抓包

  • 接下來咱們會以nginx與PHP-FPM以前通訊的數據包爲例,利用tcpdump抓取兩者通訊的數據包。因此咱們首先須要瞭解一下各層數據報頭部的格式,可是具體每一個字段的做用,咱們會在接下來詳細講解,先讓咱們熟悉一下:

數據鏈路層(以太網幀爲例)

網絡層(IPv4協議爲例)

傳輸層(TCP協議爲例)

各層之間數據包的聯繫

  • 數據鏈路層是對網絡層數據及頭部的封裝;
  • 網路層是對傳輸層數據及頭部的封裝;
  • 傳輸層是對應用層數據及頭部的封裝:

  • 因爲FastCGI協議基於TCP協議,那麼它必定會進行三次握手與四次揮手,中間的數據包是雙方的數據交換,所有的數據包以下:
[root@VM_0_3_centos ~]# tcpdump -i lo port 9000 -S -XX
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
13:50:43.883490 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [S], seq 608546013, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 0,nop,wscale 7], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  003c de3b 4000 4006 5e7e 7f00 0001 7f00  .<.;@.@.^~......
    0x0020:  0001 8434 2328 2445 acdd 0000 0000 a002  ...4#($E........
    0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 3955  ...0..........9U
    0x0040:  72e6 0000 0000 0103 0307                 r.........
13:50:43.883520 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [S.], seq 2973795481, ack 608546014, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 961901286,nop,wscale 7], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  003c 0000 4000 4006 3cba 7f00 0001 7f00  .<..@.@.<.......
    0x0020:  0001 2328 8434 b140 8499 2445 acde a012  ..#(.4.@..$E....
    0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 3955  ...0..........9U
    0x0040:  72e6 3955 72e6 0103 0307                 r.9Ur.....
13:50:43.883541 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [.], ack 2973795482, win 342, options [nop,nop,TS val 961901286 ecr 961901286], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 de3c 4000 4006 5e85 7f00 0001 7f00  .4.<@.@.^.......
    0x0020:  0001 8434 2328 2445 acde b140 849a 8010  ...4#($E...@....
    0x0030:  0156 fe28 0000 0101 080a 3955 72e6 3955  .V.(......9Ur.9U
    0x0040:  72e6                                     r.
13:50:43.883594 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [P.], seq 608546014:608546982, ack 2973795482, win 342, options [nop,nop,TS val 961901286 ecr 961901286], length 968
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  03fc de3d 4000 4006 5abc 7f00 0001 7f00  ...=@.@.Z.......
    0x0020:  0001 8434 2328 2445 acde b140 849a 8018  ...4#($E...@....
    0x0030:  0156 01f1 0000 0101 080a 3955 72e6 3955  .V........9Ur.9U
    0x0040:  72e6 0101 0001 0008 0000 0001 0000 0000  r...............
    0x0050:  0000 0104 0001 03a0 0000 0f35 5343 5249  ...........5SCRI
    0x0060:  5054 5f46 494c 454e 414d 452f 6461 7461  PT_FILENAME/data
    0x0070:  2f77 7777 2f68 7464 6f63 732f 6461 7461  /www/htdocs/data
    0x0080:  2f77 7777 2f68 7464 6f63 732f 736e 6f2f  /www/htdocs/sno/
    0x0090:  7075 626c 6963 2f69 6e64 6578 2e70 6870  public/index.php
    0x00a0:  0c00 5155 4552 595f 5354 5249 4e47 0e03  ..QUERY_STRING..
    0x00b0:  5245 5155 4553 545f 4d45 5448 4f44 4745  REQUEST_METHODGE
    0x00c0:  540c 0043 4f4e 5445 4e54 5f54 5950 450e  T..CONTENT_TYPE.
    0x00d0:  0043 4f4e 5445 4e54 5f4c 454e 4754 480b  .CONTENT_LENGTH.
    0x00e0:  0a53 4352 4950 545f 4e41 4d45 2f69 6e64  .SCRIPT_NAME/ind
    0x00f0:  6578 2e70 6870 0b01 5245 5155 4553 545f  ex.php..REQUEST_
    0x0100:  5552 492f 0c01 444f 4355 4d45 4e54 5f55  URI/..DOCUMENT_U
    0x0110:  5249 2f0d 2b44 4f43 554d 454e 545f 524f  RI/.+DOCUMENT_RO
    0x0120:  4f54 2f64 6174 612f 7777 772f 6874 646f  OT/data/www/htdo
    0x0130:  6373 2f64 6174 612f 7777 772f 6874 646f  cs/data/www/htdo
    0x0140:  6373 2f73 6e6f 2f70 7562 6c69 630f 0853  cs/sno/public..S
    0x0150:  4552 5645 525f 5052 4f54 4f43 4f4c 4854  ERVER_PROTOCOLHT
    0x0160:  5450 2f31 2e31 0e04 5245 5155 4553 545f  TP/1.1..REQUEST_
    0x0170:  5343 4845 4d45 6874 7470 1107 4741 5445  SCHEMEhttp..GATE
    0x0180:  5741 595f 494e 5445 5246 4143 4543 4749  WAY_INTERFACECGI
    0x0190:  2f31 2e31 0f0c 5345 5256 4552 5f53 4f46  /1.1..SERVER_SOF
    0x01a0:  5457 4152 456e 6769 6e78 2f31 2e31 312e  TWAREnginx/1.11.
    0x01b0:  390b 0f52 454d 4f54 455f 4144 4452 3131  9..REMOTE_ADDR11
    0x01c0:  332e 3232 372e 3234 392e 3132 370b 0552  3.227.249.127..R
    0x01d0:  454d 4f54 455f 504f 5254 3533 3931 330b  EMOTE_PORT53913.
    0x01e0:  0a53 4552 5645 525f 4144 4452 3137 322e  .SERVER_ADDR172.
    0x01f0:  3136 2e30 2e33 0b02 5345 5256 4552 5f50  16.0.3..SERVER_P
    0x0200:  4f52 5438 300b 0d53 4552 5645 525f 4e41  ORT80..SERVER_NA
    0x0210:  4d45 6772 6170 652e 7961 662e 636f 6d0f  MEgrape.yaf.com.
    0x0220:  0352 4544 4952 4543 545f 5354 4154 5553  .REDIRECT_STATUS
    0x0230:  3230 3009 0f48 5454 505f 484f 5354 3132  200..HTTP_HOST12
    0x0240:  322e 3135 322e 3232 392e 3232 310f 0a48  2.152.229.221..H
    0x0250:  5454 505f 434f 4e4e 4543 5449 4f4e 6b65  TTP_CONNECTIONke
    0x0260:  6570 2d61 6c69 7665 1209 4854 5450 5f43  ep-alive..HTTP_C
    0x0270:  4143 4845 5f43 4f4e 5452 4f4c 6d61 782d  ACHE_CONTROLmax-
    0x0280:  6167 653d 301e 0148 5454 505f 5550 4752  age=0..HTTP_UPGR
    0x0290:  4144 455f 494e 5345 4355 5245 5f52 4551  ADE_INSECURE_REQ
    0x02a0:  5545 5354 5331 0f79 4854 5450 5f55 5345  UESTS1.yHTTP_USE
    0x02b0:  525f 4147 454e 544d 6f7a 696c 6c61 2f35  R_AGENTMozilla/5
    0x02c0:  2e30 2028 4d61 6369 6e74 6f73 683b 2049  .0.(Macintosh;.I
    0x02d0:  6e74 656c 204d 6163 204f 5320 5820 3130  ntel.Mac.OS.X.10
    0x02e0:  5f31 355f 3029 2041 7070 6c65 5765 624b  _15_0).AppleWebK
    0x02f0:  6974 2f35 3337 2e33 3620 284b 4854 4d4c  it/537.36.(KHTML
    0x0300:  2c20 6c69 6b65 2047 6563 6b6f 2920 4368  ,.like.Gecko).Ch
    0x0310:  726f 6d65 2f37 352e 302e 3337 3730 2e31  rome/75.0.3770.1
    0x0320:  3030 2053 6166 6172 692f 3533 372e 3336  00.Safari/537.36
    0x0330:  0b76 4854 5450 5f41 4343 4550 5474 6578  .vHTTP_ACCEPTtex
    0x0340:  742f 6874 6d6c 2c61 7070 6c69 6361 7469  t/html,applicati
    0x0350:  6f6e 2f78 6874 6d6c 2b78 6d6c 2c61 7070  on/xhtml+xml,app
    0x0360:  6c69 6361 7469 6f6e 2f78 6d6c 3b71 3d30  lication/xml;q=0
    0x0370:  2e39 2c69 6d61 6765 2f77 6562 702c 696d  .9,image/webp,im
    0x0380:  6167 652f 6170 6e67 2c2a 2f2a 3b71 3d30  age/apng,*/*;q=0
    0x0390:  2e38 2c61 7070 6c69 6361 7469 6f6e 2f73  .8,application/s
    0x03a0:  6967 6e65 642d 6578 6368 616e 6765 3b76  igned-exchange;v
    0x03b0:  3d62 3314 0d48 5454 505f 4143 4345 5054  =b3..HTTP_ACCEPT
    0x03c0:  5f45 4e43 4f44 494e 4767 7a69 702c 2064  _ENCODINGgzip,.d
    0x03d0:  6566 6c61 7465 140e 4854 5450 5f41 4343  eflate..HTTP_ACC
    0x03e0:  4550 545f 4c41 4e47 5541 4745 7a68 2d43  EPT_LANGUAGEzh-C
    0x03f0:  4e2c 7a68 3b71 3d30 2e39 0104 0001 0000  N,zh;q=0.9......
    0x0400:  0000 0105 0001 0000 0000                 ..........
13:50:43.883602 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [.], ack 608546982, win 357, options [nop,nop,TS val 961901286 ecr 961901286], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 f67c 4000 4006 4645 7f00 0001 7f00  .4.|@.@.FE......
    0x0020:  0001 2328 8434 b140 849a 2445 b0a6 8010  ..#(.4.@..$E....
    0x0030:  0165 fe28 0000 0101 080a 3955 72e6 3955  .e.(......9Ur.9U
    0x0040:  72e6                                     r.
13:50:43.885366 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [P.], seq 2973795482:2973795650, ack 608546982, win 357, options [nop,nop,TS val 961901288 ecr 961901286], length 168
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  00dc f67d 4000 4006 459c 7f00 0001 7f00  ...}@.@.E.......
    0x0020:  0001 2328 8434 b140 849a 2445 b0a6 8018  ..#(.4.@..$E....
    0x0030:  0165 fed0 0000 0101 080a 3955 72e8 3955  .e........9Ur.9U
    0x0040:  72e6 0106 0001 008d 0300 582d 506f 7765  r.........X-Powe
    0x0050:  7265 642d 4279 3a20 5048 502f 372e 322e  red-By:.PHP/7.2.
    0x0060:  3132 0d0a 436f 6e74 656e 742d 5479 7065  12..Content-Type
    0x0070:  3a61 7070 6c69 6361 7469 6f6e 2f6a 736f  :application/jso
    0x0080:  6e3b 2063 6861 7273 6574 3d75 7466 2d38  n;.charset=utf-8
    0x0090:  0d0a 0d0a 7b22 7374 6174 7573 223a 3531  ....{"status":51
    0x00a0:  342c 226d 7367 223a 2255 6e65 7863 6570  4,"msg":"Unexcep
    0x00b0:  7465 6420 6120 656d 7074 7920 636f 6e74  ted.a.empty.cont
    0x00c0:  726f 6c6c 6572 206e 616d 6522 2c22 6461  roller.name","da
    0x00d0:  7461 223a 5b5d 7d00 0000 0103 0001 0008  ta":[]}.........
    0x00e0:  0000 0000 0000 0077 5c2f                 .......w\/
13:50:43.885378 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [.], ack 2973795650, win 350, options [nop,nop,TS val 961901288 ecr 961901288], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 de3e 4000 4006 5e83 7f00 0001 7f00  .4.>@.@.^.......
    0x0020:  0001 8434 2328 2445 b0a6 b140 8542 8010  ...4#($E...@.B..
    0x0030:  015e fe28 0000 0101 080a 3955 72e8 3955  .^.(......9Ur.9U
    0x0040:  72e8                                     r.
13:50:43.885396 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [F.], seq 2973795650, ack 608546982, win 357, options [nop,nop,TS val 961901288 ecr 961901288], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 f67e 4000 4006 4643 7f00 0001 7f00  .4.~@.@.FC......
    0x0020:  0001 2328 8434 b140 8542 2445 b0a6 8011  ..#(.4.@.B$E....
    0x0030:  0165 fe28 0000 0101 080a 3955 72e8 3955  .e.(......9Ur.9U
    0x0040:  72e8                                     r.
13:50:43.885667 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [F.], seq 608546982, ack 2973795651, win 350, options [nop,nop,TS val 961901288 ecr 961901288], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 de3f 4000 4006 5e82 7f00 0001 7f00  .4.?@.@.^.......
    0x0020:  0001 8434 2328 2445 b0a6 b140 8543 8011  ...4#($E...@.C..
    0x0030:  015e fe28 0000 0101 080a 3955 72e8 3955  .^.(......9Ur.9U
    0x0040:  72e8                                     r.
13:50:43.885678 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [.], ack 608546983, win 357, options [nop,nop,TS val 961901288 ecr 961901288], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  0034 f67f 4000 4006 4642 7f00 0001 7f00  .4..@.@.FB......
    0x0020:  0001 2328 8434 b140 8543 2445 b0a7 8010  ..#(.4.@.C$E....
    0x0030:  0165 fe28 0000 0101 080a 3955 72e8 3955  .e.(......9Ur.9U
    0x0040:  72e8                                     r.
  • 咱們能夠看到,前三個包就是TCP的三次握手,通過了必定量的數據傳輸以後,最後四個包就是TCP的四次揮手,咱們能夠用下圖來進行表示:

  • 咱們挑選第二個數據包進行詳細講解。咱們能夠分析出,它是創建TCP鏈接的三次握手中的第二次握手,是由服務端返回給客戶端的ACK包:
13:50:43.883520 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [S.], seq 2973795481, ack 608546014, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 961901286,nop,wscale 7], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500  ..............E.
    0x0010:  003c 0000 4000 4006 3cba 7f00 0001 7f00  .<..@.@.<.......
    0x0020:  0001 2328 8434 b140 8499 2445 acde a012  ..#(.4.@..$E....
    0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 3955  ...0..........9U
    0x0040:  72e6 3955 72e6 0103 0307                 r.9Ur.....
  • 每一組是4個16進制數字,因此每一組是16位,即兩個字節。
  • 因爲當前數據包是通過層層封裝的最終的數據包,因此它包含幀頭部、IP頭部、TCP頭部、以及應用程序數據(參考上圖)下面咱們逐個字節分析:

幀頭部


  • 0000 0000 0000:源MAC地址(源MAC地址是6個字節,因爲都是本機因此爲全0)
  • 0000 0000 0000:目的MAC地址(目的MAC地址是6個字節)
  • 0800:表示類型爲IP數據報(類型字段爲了區分是使用IP協議、ARP協議仍是RARP協議類型的幀)

IPv4協議頭部


  • 4:版本號爲IPv4
  • 5:IP協議頭部長度爲5 * 4(以4B爲單位計算) = 20字節
  • 00:8位服務類型
  • 003c:總長度爲60字節
  • 0000:16位標識(同一個IP數據報的全部分片的標識均相同)
  • 4000:3位標誌 + 13位片偏移(0100 0000 0000 0000)(010表明禁止分片,片偏移爲0)
  • 40:8位生存時間TTL(數據報到達目的地以前容許的路由器跳數,一般爲64)
  • 06:8位協議(用來區分上層協議,6爲TCP)
  • 3cba:16位頭部校驗和(接收端使用CRC算法檢驗IP數據報頭部是否損壞)
  • 7f00 0001:32位源端IP地址(轉化爲十進制127.0.0.1)
  • 7f00 0001:32位目的端IP地址(轉化爲十進制127.0.0.1)

TCP協議頭部


  • 2328:16位源端口號(十進制值爲9000,由於PHP-FPM的端口號爲9000)
  • 8434:16位目的端口號(十進制值爲33844,是創建初始TCP鏈接時產生的隨機端口號)
  • b140 8499:32位序號(十進制值爲2973795481,是服務端的初始序號)
  • 2445 acde:32位確認號(十進制值爲608546014,表明客戶端608546013及以前序號的報文段已所有收到)
  • a:TCP協議頭部長度爲10 * 4(以4B爲單位計算) = 40字節
  • 012:6位保留 + URG|ACK|PSH|RST|SYN|FIN (012 = 000000 010010,即ACK = 1及SYN = 1,符合三次握手規律)
  • aaaa:16位窗口大小(十進制值爲43690,告訴對方本身的TCP接收緩衝區還能容納多少字節的數據,這樣對方就能夠控制數據的發送速度)
  • fe30:16位校驗和(接收端使用CRC算法檢驗TCP數據報頭部及數據部分是否損壞,是TCP可靠傳輸的保障)
  • 0000:16位緊急指針(用來讓發送端給接收端發送緊急數據)
  • 0204 ffd7 0402 080a 3955 72e6 3955 72e6 0103 0307:20字節的TCP頭部選項

  • 當三次握手以後,TCP鏈接正式創建。咱們能夠在下面幾個包中看到具體的HTTP協議的請求行、請求主體、以及相應的返回狀態碼及響應主體等內容。
  • 咱們總結一下,FastCGI協議其實就至關於基於TCP協議的HTTP協議。在LNMP架構中,nginx是一個web服務器,只支持HTTP協議數據的輸入與輸出;而PHP-FPM只支持FastCGI協議的輸入與輸出,這裏nginx就能夠當作是一個協議轉換器的做用。它下層的TCP協議是面向字節流傳輸的,傳給對方的只是一堆的字節數據,接收方沒法解析其內容所表明的含義。那麼咱們開發HTTP協議、FastCGI協議等等也是同理。爲了可以讓PHP-FPM更加輕鬆容易地解析nginx轉發過來的數據包,讀懂基於TCP的這些字節流數據的含義,那麼咱們必須約定一種數據格式,讓數據的傳輸、讀取更加方便、高效、規範,這就是開發FastCGI協議的目的。這篇文章只是給你們一個複習以及鋪墊,具體FastCGI協議所規定的格式與詳細內容請聽下回分解。
相關文章
相關標籤/搜索