微信公衆號:[前端一鍋煮]
一點技術、一點思考。
問題或建議,請公衆號留言。
- UDP
- TCP
- 三次握手
- 四次揮手
- 擁塞控制
- HTTP
- HTTP/2
- HTTPS
- 證書認證
- 對稱加密
- 非對稱加密
- 壓縮方式
- 優化網絡請求
長篇預警~前端
UDP
UDP(User Data Protocol,用戶數據報協議)是一個面向無鏈接的傳輸層協議。webpack
- UDP 是一個非鏈接的協議,傳輸數據以前源端和終端不創建鏈接,當它想傳送時就簡單地去抓取來自應用程序的數據,並儘量快地把它扔到網絡上。在發送端,UDP 傳送數據的速度僅僅是受應用程序生成數據的速度、計算機的能力和傳輸帶寬的限制。在接收端,UDP 把每一個消息段放在隊列中,應用程序每次從隊列中讀一個消息段。
- 因爲傳輸數據不創建鏈接,所以也就不須要維護鏈接狀態,包括收發狀態等,所以一臺服務機可同時向多個客戶機傳輸相同的消息。
- UDP 信息包的標題很短,只有 8 個字節,相對於 TCP 的 20 個字節信息包的額外開銷很小。
- 吞吐量不受擁擠控制算法的調節,只受應用軟件生成數據的速率、傳輸帶寬、源端和終端主機性能的限制。
- UDP 使用盡最大努力交付,即不保證可靠交付,所以主機不須要維持複雜的連接狀態表(這裏面有許多參數)。
- UDP 是面向報文的。發送方的 UDP 對應用程序交下來的報文,在添加首部後就向下交付給 IP 層。既不拆分,也不合並,而是保留這些報文的邊界,所以,應用程序須要選擇合適的報文大小。
TCP
TCP(Transmission Control Protocol,傳輸控制協議)是一個面向鏈接的、可靠的、基於字節流的傳輸層協議。在收發數據前,必須和對方創建可靠的鏈接。一個 TCP 鏈接必須通過三次握手才能創建起來,斷開鏈接要通過四次揮手,其中的過程很是複雜。web
三次握手
名詞解釋:redis
- SYN:表示創建一個鏈接,攜帶 SYN 的 tcp 報文段爲同步報文段。
- FIN:表示告知對方本端要關閉鏈接了。
- ACK:表示確認好是否有效,攜帶 ack 標誌的報文段也稱確認報文段。只有當 ACK=1 時確認號纔有效,當 ACK=0 時確認號無效,這時會要求重傳數據,保證數據的完整性。
三次握手過程:算法
- Client:通知 Server 我要鏈接,不含應用層數據(SYN 1 => Server)。
- Server:收到 Client 通知,贊成鏈接,不含應用層數據(SYN+ACK 1 => Client)。
- Client:收到了 Server 的贊成(ACK 1 => Server TCP)
注意:數據庫
Client:沒收到重發,只接受最後一次發 SYN 的 SYN+ACK 迴應,忽略其餘迴應。gulp
Server:沒收到重發,一直沒收到 ACK,釋放資源。瀏覽器
爲何要三次握手:緩存
爲了防止無效的鏈接請求到達服務器。安全
由於有可能客戶端先發了一個鏈接請求報文,可是因爲網絡的問題,遲遲沒有到達服務器。這時候,客戶端就超時重傳了該報文,而後服務器響應了該請求報文。可是過一會,第一個報文竟然又到了服務器,那麼服務器就會把它做爲新的鏈接請求。若是隻有兩次握手,那麼服務器對於該鏈接請求也會創建鏈接,但若是是三次握手,服務器發出確認報文後,客戶端不予理睬,這樣就不會創建TCP鏈接了。
四次揮手
四次揮手過程:
- Client 我要關閉鏈接(FIN 1 => Server)
- Server 收到確認,此時 Server 還未關閉(ACK 1 => Client)
- Server 我要關了(FIN 1 => Client)
- Client 收到確認(ACK 1 => Server)
爲何要四次揮手
由於服務端在接收到 FIN, 每每不會當即返回 FIN, 必須等到服務端全部的報文都發送完畢了,才能發 FIN。所以先發一個 ACK 表示已經收到客戶端的 FIN,延遲一段時間才發 FIN。這就形成了四次揮手。
若是是三次揮手會有什麼問題?
等於說服務端將 ACK 和 FIN 的發送合併爲一次揮手,這個時候長時間的延遲可能會致使客戶端誤覺得 FIN 沒有到達客戶端,從而讓客戶端不斷的重發 FIN。
總結:鏈接要快,關閉要等。鏈接不須要等待而要儘可能快,因此第二次握手 SYN+ACK 和到一塊兒發送。關閉鏈接要等,由於數據可能尚未傳完,還在路上繼續傳,因此分開,先告訴客戶端已經收到了通知不用再發第二遍了。等數據全傳完了再通知客戶端我也關閉了。
擁塞控制
tcp 用一系列方法來確保數據的可靠性:去錯去重、失序重排、超時重發、應答機制、流量控制、擁塞控制。
- 流量控制:經過接收緩存區的大小,控制發送端的發送。若是對方的接收緩存區滿了,就不能再繼續發送了。
- 慢啓動:擁塞窗口 cwnd 翻倍加大,由小到大根據反饋逐漸增大擁塞窗口。
- 擁塞避免:加大到慢啓動閾值的時候,每次加 1。
- 快速重傳:若是發生了丟包,即接收端發現數據段不是按序到達的時候,接收端的處理是重複發送以前的 ACK。發送方只要一連收到三個重複確認就應當當即重傳對方還沒有收到的報文段,而沒必要繼續等待設置的重傳計時器到期。
- 選擇性重傳:SACK 記錄一下哪些包到了,哪些沒到,針對性地重傳。
- 快速恢復:擁塞閾值下降爲 cwnd 的一半,cwnd 的大小變爲擁塞閾值,cwnd 線性增長。
HTTP
HTTP 協議,是 Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。
HTTP 是一個無狀態的協議。無狀態是指瀏覽器和服務器之間不須要創建持久的鏈接,這意味着當一個客戶端向服務器端發出請求,而後服務器返回響應,鏈接就被關閉了,在服務器端不保留鏈接的有關信息。
HTTP1.0 最先在網頁中使用是在 1996年,使用在一些較爲簡單的網頁上和網絡請求上,HTTP1.1 則在 1999年纔開始普遍應用於如今的各大瀏覽器網絡請求中,同時 HTTP1.1 也是當前使用最爲普遍的 HTTP 協議。主要區別體如今:
- 持久鏈接:HTTP1.1 支持持久鏈接,默認開啓 Connection: keep-alive,即 TCP 鏈接默認不關閉,能夠被多個請求複用(對於同一個域名,大多數瀏覽器容許同時創建 6 個持久鏈接),必定程度上彌補了 HTTP1.0 每次請求都要建立鏈接的缺點。
- 斷點續傳:HTTP1.0 不支持斷點續傳功能,HTTP1.1 則在請求頭引入了 range 頭域,容許只請求資源的某個部分,返回碼是 206。
- 緩存處理:在 HTTP1.0 中主要使用 header 裏的 If-Modified-Since、Expires 來作爲緩存判斷的標準,HTTP1.1 則引入了更多的緩存控制策略如 Entity tag、If-Unmodified-Since、If-Match,、If-None-Match 等更多可供選擇的緩存頭來控制緩存策略。
- 錯誤通知的管理:HTTP1.1 新增了 24 個錯誤狀態響應碼,如 409 表示請求的資源與資源的當前狀態發生衝突;410 表示服務器上的某個資源被永久性的刪除。
- Host頭處理:HTTP1.0 中認爲每臺服務器都綁定一個惟一的 IP 地址,所以,請求消息中的 URL 並無傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一臺物理服務器上能夠存在多個虛擬主機(Multi-homed Web Servers),而且它們共享一個 IP 地址。HTTP1.1 的請求消息和響應消息都應支持 Host 頭域,且請求消息中若是沒有 Host 頭域會報告一個錯誤(400 Bad Request)。
缺點:
雖然容許複用 TCP 鏈接,可是同一個 TCP 鏈接裏面,全部的數據通訊是按次序進行的。服務器只有處理完一個請求,纔會接着處理下一個請求。若是前面的處理特別慢,後面就會有許多請求排隊等着。這將致使「隊頭堵塞」。
避免方式:一是減小請求數,二是同時多開持久鏈接。
HTTP/2
HTTP/2 是 HTTP 協議自 1999 年 HTTP 1.1 發佈後的首個更新,主要基於 SPDY 協議,於 2015年5月以 RFC 7540 正式發表。
主要有如下改進:
- 二進制協議:HTTP/1.1 版的頭信息確定是文本(ASCII編碼),數據體能夠是文本,也能夠是二進制。HTTP/2 則是一個完全的二進制協議,頭信息和數據體都是二進制,而且統稱爲」幀」:頭信息幀和數據幀。二進制協議解析起來更高效、「線上」更緊湊,更重要的是錯誤更少。
- 多路複用:HTTP/2 複用 TCP 鏈接,在一個鏈接裏,客戶端和瀏覽器均可以同時發送多個請求或迴應,並且不用按照順序一一對應,這樣就避免了」隊頭堵塞」。
- 頭信息壓縮:HTTP 協議是沒有狀態,致使每次請求都必須附上全部信息。請求的不少頭字段都是重複的,好比 Cookie,同樣的內容每次請求都必須附帶,這會浪費不少帶寬,也影響速度。HTTP/2 對這一點作了優化,引入了頭信息壓縮機制。一方面,頭信息使用 gzip 或 compress 壓縮後再發送。另外一方面,客戶端和服務器同時維護一張頭信息表,全部字段都會存入這個表,產生一個索引號,以後就不發送一樣字段了,只需發送索引號。這樣對於相同的頭部,沒必要再經過請求發送,只需發送一次。
- 服務器推送:HTTP/2 容許服務器未經請求,主動向客戶端發送資源。
HTTPS
HTTP 協議一般承載於 TCP 協議之上,在 HTTP 和 TCP 之間添加一個安全協議層(SSL或TSL),就成了咱們常說的 HTTPS。
HTTPS 主要用到對稱加密、非對稱加密、證書,等技術進行客戶端與服務器的數據加密傳輸,最終達到保證整個通訊的安全性。
證書認證
服務端證書:SSL 客戶端經過 TCP 和服務器創建鏈接以後(443 端口),而且在通常的 tcp 鏈接協商(握 手)過程當中請求證書。即客戶端發出一個消息給服務器,這個消息裏面包含了本身可實現的算法列表和其它一些須要的消息,SSL 的服務器端會迴應一個數據包,這裏面肯定了此次通訊所須要的算法,而後服務器向客戶端返回證書(證書裏面包含了域名、申請證書的公司、公共祕鑰等信息)。
證書驗證:客戶端安裝了第三方 CA 的根證書,該根證書下的全部證書都將被客戶端信任。在收到服務器返回的證書後,使用這個機構的公共祕鑰解密簽名,獲得服務端公鑰及其餘信息。作數字簽名,若是一致,則確認證書合法即服務端被信任。客戶端還會確保證書中列出的域名就是它正在鏈接的域名。
數字簽名:第三方認證機構私鑰加密給服務器的證書,瀏覽器獲取第三方認證機構公鑰解密,客戶端利用簽名生成規則進行簽名生成,看兩個簽名是否匹配。
數據加密和傳輸:若是確認證書有效,那麼生成對稱祕鑰並使用服務器的公共祕鑰進行加密。而後發送給服務器,服務器使用它的私鑰對它進行解密,這樣兩臺計算機能夠開始進行對稱加密進行通訊。
對稱加密
對稱密鑰加密,是指加密和解密使用同一個密鑰的方式,加密和解密的算法是公開的,密鑰是隱祕的,流行的對稱加密算法有:DES、AES。
AES:AES-12八、AES-25六、AES-192。
缺點:
- 密鑰分發問題,如何安全的把共享密鑰在雙方進行分享,這自己也是一個如何安全通訊的問題。一種方法是提早雙方約定好,不經過具體的通訊進行協商,避免被監聽和截獲。另一種方式,將是下面咱們介紹的經過非對稱加密信道進行對稱密碼的分發和共享,即混合加密系統。
- 密鑰管理的複雜度問題,對稱加密的密鑰是一對一的使用方式,若一方要跟n方通訊,則須要維護 n 對密鑰。
優勢:
- 加密和解密的速度要比非對稱加密快不少。
- 密鑰 k 的長度越長,對應的密碼空間就越大,暴力破解難度越大,就更加安全。
非對稱加密
非對稱加密,指使用一對非對稱密鑰,即公鑰和私鑰,公鑰能夠隨意發佈,但私鑰只有本身知道。發送密文的一方使用對方的公鑰進行加密處理,對方接收到加密信息後,使用本身的私鑰進行解密。
經常使用的非對稱加密算法有 RSA:md五、SHA-1,SHA-224,SHA-256,SHA-512,SHA-384。
非對稱加密過程:
- 服務端生成配對的公鑰和私鑰。
- 私鑰保存在服務端,公鑰發送給客戶端。
- 客戶端使用公鑰加密明文傳輸給服務端。
- 服務端使用私鑰解密密文獲得明文。
用公鑰加密的密文,只有擁有私鑰的一方纔能解密,這樣加密的各方統一使用一個公鑰便可。
優勢:不存在密鑰分發的問題,解碼方能夠本身生成密鑰對,一個作私鑰存起來,另一個做爲公鑰進行發佈。解決了密鑰管理的複雜度問題,多個加密方均可以使用一個已知的公鑰進行加密,但只有擁有私鑰的一方纔能解密。
缺點: 加解密的速度沒有對稱加密快。
四次握手
HTTPS 要通過四次握手創建鏈接,雙方生成會話密鑰。
- Client:一個隨機數 Client.random。支持的協議版本,好比TLS 1.0版。支持的加密方法,好比 RSA 公鑰加密。
- Sever:一個隨機數 Server.random。確認使用的加密方法,確認協議。服務器證書:攜帶服務器證書鏈,其中有兩個證書,第一個是域名的證書,第二個是 CA 證書,用於驗證第一個證書的正確性。那如何驗證第二個 CA 證書是否被篡改過呢?使用瀏覽器內置的根證書去驗證。
- Client:一個隨機數 pre-master,編碼改變通知,表示隨後的信息都將用雙方商定的加密方法和密鑰發送,客戶端握手結束通知。
- Sever:編碼改變通知,表示隨後的信息都將用雙方商定的加密方法和密鑰發送,服務器握手結束通知。
四次握手耗時大概是TCP的三倍,保密強度越高的數字證書耗時越長。經歷如下過程:
版本+隨機數+加密方法;
確認版本+隨機數+確認加密方法+服務器證書(服務器證書+中間 CA 證書 根證書);
公鑰加密過的隨機數+編碼改變通知+結束通知;
編碼改變通知+結束通知。
這樣客戶端和服務器就同時有了三個隨機數,接着雙方就用事先商定的加密方法,各自生成本次會話所用的同一把"會話密鑰"。
session ID
SSL 中的 session 會跟 HTTP 的 session 相似,都是用來保存客戶端和服務端之間交互的一些記錄。這裏的 SSL 的 session 保存的是 SSL 的握手記錄。
SSL 握手過程,由於多了幾回 RTT,還有加解密的計算,是 HTTPS 的耗時大戶,優化的重點。複用了握手記錄,能夠很顯著地提升 HTTPS 的效率。
session ID:服務端保存握手記錄,客戶端 session ID 會話編號發給服務端驗證,只有一臺服務器有。
session ticket:客戶端保存握手記錄,客戶端加密的 session ticket 給服務端解密獲得上次會話信息,多服務器均可解密獲得。
壓縮方式
瀏覽器 Content-Encoding 值:
- gzip:代表實體採用 GUN zip 編碼
- compress:代表實體採用 Unix 的文件壓縮程序
- deflate:代表實體使用 zlib 的格式壓縮
- identity:代表不對實體進行編碼,當沒有 Content-Encoding 首部的時候,就默認爲這種狀況
- br:代表實體採用 Brotli 算法編碼 一種比 Gzip 壓縮率更高的算法,只在 HTTPS 中生效,由於在 HTTP 請求中 request header 裏的 Accept-Encoding 是沒有 br 這個選項
使用 gzip 壓縮文本很是合適,但 png、gif、jpg、jpeg 這類圖片文件並不推薦使用 gzip 壓縮(svg是個例外),由於通過本地壓縮處理後的圖片文件 gzip 能壓縮的空間很小。事實上,添加標頭,壓縮字典,並校驗響應體可能會讓它更大。
優化網絡請求
如下是瀏覽器中一個網絡請求的完整過程。
Stalled 檢測有沒有鏈接資源
瀏覽器獲得要發出這個請求的指令,到請求能夠發出的等待時間。通常是代理協商、以及等待可複用的 TCP 鏈接釋放的時間,不包括 DNS 查詢、創建 TCP 鏈接等時間等。
- 單一服務發送時候 stalled 過長,每每是丟包所致,這也意味着網絡或服務端有問題;
- 多個服務併發致使 stalled 過長,是瀏覽器對同一個主機域名的併發鏈接數有限制,過長的請求是被阻塞了,處在隊列中等待 tcp 鏈接。
DNS Lookup(域名解析)
在 DNS 查找完成以前,瀏覽器不能從主機名那裏下載到任何東西。
- 利用 DNS 緩存(設置TTL時間);
- 利用 Connection: keep-alive 特性創建持久鏈接,能夠在當前鏈接上進行多個請求,無需再進行域名解析。
Initial connection(初始化鏈接)
TCP 創建鏈接的三次握手時間。
Request sent 請求發完
請求第一個字節發出前到最後一個字節發出後的時間,也就是上傳時間。
- 減小 HTTP 請求,可使用 CSS Sprites、內聯圖片、合併腳本和樣式表等;
- 對不常變化的組件添加長久的 Expires 頭(至關於設置久遠的過時時間),在後續的頁面瀏覽中能夠避免沒必要要的 HTTP 請求。
Waiting 等待服務器響應
請求發出後,到收到響應的第一個字節所花費的時間。一般是耗費時間最長的。從發送請求到收到響應之間的空隙,會受到線路、服務器距離等因素的影響。
- 經過優化數據庫查詢條件、數據緩存到 redis 中來加快數據返回速度;
- 使用 CDN,將用戶的訪問指向距離最近的工做正常的緩存服務器上,由緩存服務器直接響應用戶請求,提升響應速度。
Content Download 下載完
收到響應的第一個字節,到接受完最後一個字節的時間,就是下載時間。
- 移除重複腳本,精簡和壓縮代碼,如藉助自動化構建工具 webpack、grunt、gulp 等;
- 壓縮響應內容,服務器端啓用 gzip 壓縮,能夠減小下載時間。