天天看點

分布式架構基礎-遠端通信tcp/ip協定原理

作者:京城小人物

1、一個http請求的流程

在分布式架構中,有一個很重要的環節,就是分布式網絡中的計算機節點彼此之間需要通信。這個通信的過程一定會涉及到通信協定相關的知識點,

我們每天都在用浏覽器通路各種網站,作為使用者來說,隻需要需要輸入一個網址并且正确跳轉就行。但是作為程式員,看到的可能就是這個響應背後的整體流程。是以我們通過一個 http請求的整個流程來進行說明遠端通信的原理

域名解析服務DNS

首先,使用者通路一個域名,會經過 DNS 解析DNS(Domain Name System),它和 HTTP 協定一樣是位于應用層的協定,主要提供域名到IP 的解析服務。我們其實不用域名也可以通路目标主機的服務,但是 IP 本身不是那麼容易記,是以使用域名進行替換使得使用者更容易記住。

分布式架構基礎-遠端通信tcp/ip協定原理

靜态内容分發CDN

在很多大型網站,會引入 CDN 來加速靜态内容的通路,這裡簡單給大家解釋一下什麼是 CDN(Content Delivery Network),表示的是内容分發網絡。CDN 其實就是一種網絡緩存技術,能夠把一些相對穩定的資源放到距離最終使用者較近的地方,一方面可以節省整個廣域網的帶寬消耗,另外一方面可以提升使用者的通路速度,改進使用者體驗。我們一般會把靜态的檔案(圖檔、腳本、靜态頁面)放到 CDN 中。

http協定通信原理

域名被成功解析以後,用戶端和服務端之間,是怎麼建立連接配接并且如何通信的呢?

說到通信,大家一定聽過 tcp 和 udp 這兩種通信協定,以及建立連接配接的握手過程。而 http 協定的通信是基于 tcp/ip 協定之上的一個應用層協定,應用層協定除了 http 還有哪些呢(FTP、DNS、SMTP、Telnet 等)。

涉及到網絡協定,我們一定需要知道 OSI 七層網絡模型和 TCP/IP 四層概念模型,OSI 七層網絡模型包含(應用層、表示層、會話層、傳輸層、網絡層、資料鍊路層、實體層)、TCP/IP 五層概念模型包含(應用層、傳輸層、網絡層、資料鍊路層、實體層)。

分布式架構基礎-遠端通信tcp/ip協定原理

請求發起過程

當應用程式用 T C P 傳送資料時,資料被送入協定棧中,然後逐個通過每一層直到被當作一串bit流送入網絡。其中每一層對收到的資料都要增加一些首部資訊(有時還要增加尾部資訊)

分布式架構基礎-遠端通信tcp/ip協定原理

用戶端如何找到目标服務

在用戶端發起請求的時候,我們會在資料鍊路層去組裝目标機器的 MAC 位址,目标機器的mac 位址怎麼得到呢?

這裡就涉及到一個 ARP 協定,這個協定簡單來說就是已知目标機器的 ip,需要獲得目标機器的 mac 位址。(發送一個廣播消息,這個 ip 是誰的,請來認領。認領 ip 的機器會發送一個 mac 位址的響應,為了避免每次都用 ARP 請求,機器本地也會進行 ARP 緩存。當然機器會不斷地上線下線,IP 也可能會變,是以 ARP 的 MAC 位址緩存過一段時間就會過期。)

有了這個目标 MAC 位址,資料包在鍊路上廣播,MAC 的網卡才能發現,這個包是給它的。MAC 的網卡把包收進來,然後打開 IP 包,發現 IP 位址也是自己的,再打開 TCP 包,發現端口是自己,也就是 80 端口,而這個時候這台機器上有一個 nginx 是監聽 80 端口。于是将請求送出給 nginx,nginx 傳回一個網頁。然後将網頁需要發回請求的機器。然後層層封裝,最後到 MAC 層。因為來的時候有源 MAC 位址,傳回的時候,源 MAC 就變成了目标 MAC,再返給請求的機器。

接收端收到資料包以後的處理過程

當目的主機收到一個以太網資料幀時,資料就開始從協定棧中由底向上升,同時去掉各層協定加上的封包首部。每層協定都要去檢查封包首部中的協定辨別,以确定接收資料的上層協定。

分布式架構基礎-遠端通信tcp/ip協定原理

為什麼有了 MAC 層還要走 IP 層呢?

之前我們提到,mac 位址是唯一的,那理論上,在任何兩個裝置之間,我應該都可以通過mac 位址發送資料,為什麼還需要 ip 位址?

mac 位址就好像個人的身份證号,人的身份證号和人戶口所在的城市,出生的日期有關,但是和人所在的位置沒有關系,人是會移動的,知道一個人的身份證号,并不能找到它這個人,mac 位址類似,它是和裝置的生産者,批次,日期之類的關聯起來,知道一個裝置的mac,并不能在網絡中将資料發送給它,除非它和發送方的在同一個網絡内。

是以要實作機器之間的通信,我們還需要有 ip 位址的概念,ip 位址表達的是目前機器在網絡中的位置,類似于城市名+道路号+門牌号的概念。通過 ip 層的尋址,我們能知道按何種路徑在全世界任意兩台 Internet 上的的機器間傳輸資料

TCP/IP 的分層管理

TCP/IP 協定按照層次分為 5 層:應用層、傳輸層、網絡層、資料鍊路層、實體層,複雜的程式都需要分層,這個是軟體設計的要求,每一層專注于目前領域的事情。如果某些地方需要修改,我們隻需要把變動的層替換掉就行,一方面改動影響較少,另一方面整個架構的靈活性也更高。最後,在分層之後,整個架構的設計也變得相對簡單了。

分層負載

了解了分層的概念以後,我們再去了解所謂的二層負載、三層負載、四層負載、七層負載就容易多了。

一次 http 請求過來,一定會從應用層到傳輸層,完成整個互動。隻要是在網絡上跑的資料包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。

二層負載

二層負載是針對 MAC,負載均衡伺服器對外依然提供一個 VIP(虛 IP),叢集中不同的機器采用相同 IP 位址,但是機器的 MAC 位址不一樣。當負載均衡伺服器接受到請求之後,通過改寫封包的目标 MAC 位址的方式将請求轉發到目标機器實作負載均衡

二層負載均衡會通過一個虛拟 MAC 位址接收請求,然後再配置設定到真實的 MAC 位址

三層負載均衡

三層負載是針對 IP,和二層負載均衡類似,負載均衡伺服器對外依然提供一個 VIP(虛 IP),但是叢集中不同的機器采用不同的 IP 位址。當負載均衡伺服器接受到請求之後,根據不同的負載均衡算法,通過 IP 将請求轉發至不同的真實伺服器

三層負載均衡會通過一個虛拟 IP 位址接收請求,然後再配置設定到真實的 IP 位址

四層負載均衡

四層負載均衡工作在 OSI 模型的傳輸層,由于在傳輸層,隻有 TCP/UDP 協定,這兩種協定中除了包含源 IP、目标 IP 以外,還包含源端口号及目的端口号。四層負載均衡伺服器在接受到用戶端請求後,以後通過修改資料包的位址資訊(IP+端口号)将流量轉發到應用伺服器。

四層通過虛拟 IP + 端口接收請求,然後再配置設定到真實的伺服器

七層負載均衡

七層負載均衡工作在 OSI 模型的應用層,應用層協定較多,常用 http、radius、dns 等。七層負載就可以基于這些協定來負載。這些應用層協定中會包含很多有意義的内容。比如同一個Web 伺服器的負載均衡,除了根據 IP 加端口進行負載外,還可根據七層的 URL、浏覽器類别來決定是否要進行負載均衡

七層通過虛拟的 URL 或主機名接收請求,然後再配置設定到真實的伺服器。

2、tcp/ip協定深入分析

通過上面基本清楚了網絡的通信流程,在 http 協定中,底層用到了 tcp 的通信協定,接下來看看 tcp 的通信協定原理

分布式架構基礎-遠端通信tcp/ip協定原理

tcp握手協定

是以 TCP 消息的可靠性首先來自于有效的連接配接建立,是以在資料進行傳輸前,需要通過三次握手建立一個連接配接,所謂的三次握手,就是在建立 TCP 連結時,需要用戶端和服務端總共發送 3 個包來确認連接配接的建立,在 socket 程式設計中,這個過程由用戶端執行 connect 來觸發

  1. 第 一 次 握 手(SYN=1, seq=x)客 戶 端 發 送 一 個TCP 的 SYN 标志位置 1 的包,指明用戶端打算連接配接的伺服器的端口,以及初始序号 X,儲存在 包 頭 的 序 列 号(SequenceNumber)字段裡。發送完畢後,用戶端 進 入SYN_SEND 狀态。
  2. 第 二 次 握 手(SYN=1, ACK=1,seq=y,ACKnum=x+1):伺服器發回确認包(ACK) 應 答 。即SYN 标志位和ACK 标 志 位 均 為1。伺服器端選擇自己 ISN 序列号,放到 Seq 域裡,同時将 确 認 序 号(Acknowledgement Number)設定為客戶的 ISN 加 1,即 X+1。發送完畢後,伺服器 端 進 入SYN_RCVD 狀态。
  3. 第 三 次 握 手(ACK=1 ,ACKnum=y+1)用戶端再次發送确認包(ACK),SYN 标志位為 0,ACK 标志位為 1,并且把伺服器發來 ACK 的序号字段+1,放在确定字段中發送給對方,并且在資料段放寫 ISN 發完畢後 , 客 戶 端 進 入ESTABLISHED 狀态,當伺服器端接收到這個包時,也進 入ESTABLISHED 狀态,TCP 握手結束。

SYN 攻擊

在三次握手過程中,Server 發送 SYN-ACK 之後,收到 Client 的 ACK 之前的 TCP 連接配接稱為半連接配接(half-open connect),此時 Server 處于 SYN_RCVD 狀态,當收到 ACK 後,Server轉入 ESTABLISHED 狀态。SYN 攻擊就是 Client 在短時間内僞造大量不存在的 IP 位址,并向Server 不斷地發送 SYN 包,Server 回複确認包,并等待 Client 的确認,由于源位址是不存在的,是以,Server 需要不斷重發直至逾時,這些僞造的 SYN 包将産時間占用未連接配接隊列,導緻正常的 SYN 請求因為隊列滿而被丢棄,進而引起網絡堵塞甚至系統癱瘓。SYN 攻擊時一種典型的 DDOS 攻擊,檢測 SYN 攻擊的方式非常簡單,即當 Server 上有大量半連接配接狀态且源 IP 位址是随機的,則可以斷定遭到 SYN 攻擊了

TCP 四次揮手協定

四次揮手表示 TCP 斷開連接配接的時候,需要用戶端和服務端總共發送 4 個包以确認連接配接的斷開;用戶端或伺服器均可主動發起揮手動作(因為 TCP 是一個全雙工協定),在 socket 程式設計中,任何一方執行 close() 操作即可産生揮手操作

分布式架構基礎-遠端通信tcp/ip協定原理
  1. 第一次揮手(FIN=1,seq=x):假設用戶端想要關閉連接配接,用戶端發送一個 FIN 标志位置為 1 的包,表示自己已經沒有資料可以發送了,但是仍然可以接受資料。發送完畢後,用戶端進入 FIN_WAIT_1 狀态。
  2. 第二次揮手(ACK=1,ACKnum=x+1):伺服器端确認用戶端的 FIN 包,發送一個确認包,表明自己接受到了用戶端關閉連接配接的請求,但還沒有準備好關閉連接配接。發送完畢後,伺服器端進入 CLOSE_WAIT 狀态,用戶端接收到這個确認包之後,進入 FIN_WAIT_2 狀态,等待伺服器端關閉連接配接。
  3. 第三次揮手(FIN=1,seq=w):伺服器端準備好關閉連接配接時,向用戶端發送結束連接配接請求,FIN 置為 1。發送完畢後,伺服器端進入 LAST_ACK 狀态,等待來自用戶端的最後一個 ACK。
  4. 第四次揮手(ACK=1,ACKnum=w+1):用戶端接收到來自伺服器端的關閉請求,發送一個确認包,并進入 TIME_WAIT 狀态,等待可能出現的要求重傳的 ACK 包。伺服器端接收到這個确認包之後,關閉連接配接,進入 CLOSED 狀态。

用戶端等待了某個固定時間(兩個最大段生命周期,2MSL,2 Maximum Segment Lifetime)之後,沒有收到伺服器端的 ACK,認為伺服器端已經正常關閉連接配接,于是自己也關閉連接配接,進入 CLOSED 狀态

問題

【問題 1】為什麼連接配接的時候是三次握手,關閉的時候卻是四次握手?

答:三次握手是因為因為當 Server 端收到 Client 端的 SYN 連接配接請求封包後,可以直接發送SYN+ACK 封包。其中 ACK 封包是用來應答的,SYN 封包是用來同步的。但是關閉連接配接時,當 Server 端收到 FIN 封包時,很可能并不會立即關閉 SOCKET(因為可能還有消息沒處理完),是以隻能先回複一個 ACK 封包,告訴 Client 端,"你發的 FIN 封包我收到了"。隻有等到我 Server 端所有的封包都發送完了,我才能發送 FIN 封包,是以不能一起發送。故需要四步握手。

【問題 2】為什麼 TIME_WAIT 狀态需要經過 2MSL(最大封包段生存時間)才能傳回到 CLOSE狀态?

答:雖然按道理,四個封包都發送完畢,我們可以直接進入 CLOSE 狀态了,但是我們必須假象網絡是不可靠的,有可以最後一個 ACK 丢失。是以 TIME_WAIT 狀态就是用來重發可能丢失的 ACK 封包。

繼續閱讀