程序員每天都在寫代碼,關注的都是更高層次的封裝,今天咱們換個思路,讓程序那些事來帶你看一看隱藏在表象之下的網絡和他們的性能分析。程序員
本文主要涉及5個模塊,分別是網絡七層協議,延遲與帶寬,IP,TCP,UDP。緩存
在講網絡以前,必定要提到OSI網絡七層協議。服務器
OSI是Open System Interconnect的縮寫,意爲開放式系統互聯。網絡
上圖是你們很是很是熟悉的OSI七層網絡模型,和對應的TCP/IP模型。併發
應用層的功能是文件傳輸,電子郵件和文件服務等。使用的協議主要是HTTP,SMTP和FTP。ide
表示層的功能是數據格式化,代碼轉換和數據加密。性能
會話層的功能是解除或者創建與其餘節點的聯繫。學習
傳輸層的功能是提供端對端的接口,使用的協議主要是TCP和UDP。大數據
網絡層的功能是爲數據包選擇路由,使用的協議是IP。網站
數據鏈路層的功能是傳輸有地址的幀,和檢查數據錯誤。
物理層的功能是以二進制數據在物理媒介上傳輸數據。
最近電信業務員總是給我打電話,說是要把家裏的電信寬帶從100M升級到500M,天天只須要一塊錢。一塊錢雖然少,但也是血汗錢。那麼辦仍是不辦呢?升級到500M對性能和延時提高有多大幫助呢?
2020年能夠稱爲中國5G的元年。先無論華爲,中信在5G基站和協議制定方面的能力。直觀的感受5G手機開始多了,手機營業廳也在賣力的讓你升級到5G套餐,那麼辦仍是不辦?
在回答這兩個問題以前,咱們學習兩個名詞:
延遲: 分組從信息源發送到目的地所需的時間。
帶寬: 邏輯或物理通訊路徑最大的吞吐量。
若是你訪問一個網站,好比www.flydean.com,咱們看一下數據是怎麼從服務器到達你的電腦的。
首先數據從服務器經過以太網(以太網是一種計算機局域網技術)傳輸到ISP。
ISP是啥呢?ISP就是互聯網服務提供商(Internet Service Provider),經過ISP你纔可以把服務器接入互聯網。
互聯網就是經過主幹網的互聯網服務提供商(ISP)之間的相互鏈接構成的。
因此ISP就是一個......大代理。
好了,數據傳到爲我家提供服務的ISP了,而後經過光纖或者電纜線傳到了我家的WiFi,而後經過WiFi的無線信號,被個人電腦接收。
討論分析了數據的傳輸線路,接下來咱們看一下,延時會跟哪些緣由有關呢?
首先確定是信號傳輸的距離,距離越長,傳輸速率越慢,須要的時間就越長。
接下來就是消息的長度,咱們把消息中的全部比特轉移到鏈路中須要時間,消息長度越長,須要的時間越多。
數據上了鏈路以後,處理分組首部、檢查位錯誤及肯定分組目標也須要時間。
最後,咱們對於分組數據進行排隊處理也須要時間。
如今主網絡的傳輸介質基本上都是光纖了,光在光纖中傳播,並非直線進行的,而且也有折射率的影響,因此速度比光在真空中傳播要慢一點。
好比說信號圍繞赤道轉一圈,只須要大概200ms。已經很快了。
200ms確實很快了,可是對於某些實時性要求特別高的應用場景,咱們可使用CDN技術(Content Delivery Network,內容分發網絡),把內容部署在全球網絡中,而後從最近的地方去取數據。從而大大減小傳輸延時。
200ms夠快了,可是爲何咱們仍然會感受到網速慢呢?
你們都聽過木桶原理吧,木桶可以裝的水,決定於最短的那塊木板。一樣的對於網絡延時來講,提高速度不在於你在主幹網上採用了多麼先進的技術,由於提高的再多或者再差也是毫米級的。
真正決定網速的在於最後一千米,也就是你電纜線的傳輸速率,你的wifi的傳輸速率,還有你電腦的處理速率等。
能接入更高帶寬當然好,特別是傳輸大塊數據時更是如此,好比在線聽音樂、看視頻,或者下載大文件。但是,平常上網瀏覽須要的是從數十臺主機獲取較小的資源,這時候往返時間就成了瓶頸。
IP,即 Internet Protocol(因特網協議),負責聯網主機之間的路由選擇和尋址。
各類物理網絡在鏈路層所傳輸的基本單元爲幀(MAC幀),其幀格式隨物理網絡而異,各物理網絡的物理地址(MAC地址)也隨物理網絡而異。Ip協議的做用就是向傳輸層(TCP層)提供統一的IP包,即將各類不一樣類型的MAC幀轉換爲統一的IP包,並將MAC幀的物理地址變換爲全網統一的邏輯地址(IP地址)。
數據包(data packet)是什麼?
數據包也是分組交換的一種形式,就是把所傳送的數據分段打成包,再傳送出去.
每一個數據包都有報頭和報文這兩個部分,報頭中有目的地址等必要內容,使每一個數據包不通過一樣的路徑都能準確地到達目的地。在目的地從新組合還原成原來發送的數據.
咱們看下IP數據包的構成。
注意上面的Total Length部分佔用了2個字節,因此IP數據包的最大長度就是2^16-1=65535字節。
鏈路層具備最大傳輸單元MTU這個特性,它限制了數據幀的最大長度,不一樣的網絡類型都有一個上限值.若是IP層有數據包要傳,並且數據包的長度超過了MTU,那麼IP層就要對數據包進行分片操做,使每一片的長度都小於或等於MTU。
分片後的IP數據包,只有到達目的地才能從新組裝。從新組裝由目的地的IP層來完成,其目的是使分片和從新組裝過程對傳輸層(TCP和UDP)是透明的。
MSS最大傳輸大小的縮寫,是TCP協議裏面的一個概念。
MSS就是TCP數據包每次可以傳輸的最大數據分段。爲了達到最佳的傳輸效能TCP協議在創建鏈接的時候一般要協商雙方的MSS值,這個值TCP協議在實現的時候每每用MTU值代替(須要減去IP數據包包頭的大小20Bytes和TCP數據段的包頭20Bytes), 通信雙方會根據雙方提供的MSS值得最小值肯定爲此次鏈接的最大MSS值。
而通常以太網MTU都爲1500, 因此在以太網中, 每每TCP MSS爲1460。
TCP,即 Transmission Control Protocol(傳輸控制協議),負責在不可靠的傳輸信道之上提供可靠的抽象層, 嚮應用層隱藏了大多數網絡通訊的複雜細節,好比丟包重發、按序發送、擁塞控制及避免、數據完整,等等。
通常來講,使用TCP協議,若是client和server要達成一致創建鏈接的話,須要三次交互。
客戶端選擇一個隨機序列號x,併發送一個SYN 分組,其中可能還包括其餘TCP標誌和選項。
服務器給x 加1,並選擇本身的一個隨機序列號y,追加本身的標誌和選項,而後返回響應。
客戶端給x 和y 加1 併發送握手期間的最後一個ACK 分組。
若是幾個IP分組同時到達路由器,並指望經同一個輸出端口轉發.
顯然,不是全部分組能夠同時接受處理,必須有一個服務順序,中間節點上的緩存爲等候服務的分組提供必定保護。
然而,若是此情況具備必定的持續性,當緩存空間被耗盡時,路由器只有丟棄分組。
在這種持續過載的狀態下,網絡性能會急劇降低.
流量控制是一種預防發送端過多向接收端發送數據的機制。不然,接收端可能由於忙碌、負載重或緩衝區既定而沒法處理。
爲實現流量控制,TCP鏈接的每一方都要通告本身的接收窗口receive window(rwnd),其中包含可以保存數據的緩衝區空間大小信息。
最初的TCP規範分配給通告窗口大小的字段是16位的,這至關於設定了發送端和接收端窗口的最大值(65535字節)。結果,在這個限制內常常沒法得到最優性能。
爲解決這個問題,RFC1323提供了TCP窗口縮放(TCP Window Scaling)選項,能夠把接收窗口大小由65535字節提升到1G字節。
那麼如今問題來了,rwnd只是一個接收端的初始窗口大小,若是有多個sender都在向receiver發送數據包的話,怎麼才能保證receiver端的接收性能呢?
爲了解決這個問題,TCP引入了慢啓動的概念。
當sender和receiver已經創建好了TCP三次握手以後。就能夠開始發送數據包了。
這裏引入了一個擁堵窗口Congestion window(cwnd)的概念。
cwnd是server端目前能夠接受的最大的窗口大小。
創建鏈接以後第一次發送的cwnd是一個初始值,這個初始值最開始是1個network segment,在1999年 RFC 2581將其更新爲4個network segments。在2013年, RFC 6928 將這個值擴大到了10個network segments。
咱們以10個network segments爲例,看下cwnd的膨脹過程:
通常來講cwnd是倍數增長的,收到ack以後,cwnd會從10,20,40這樣往上增長。一直到server端拒絕ack爲止。
那麼回到咱們以前講到的一個結論,帶寬其實不是那麼重要。
爲何呢?考慮在HTTP1.1中,client須要等待server的返回纔可以進行下一次請求。若是你的請求的文件比較小,那麼cwnd尚未漲到足夠大的時候,請求就已經結束了。這個時候最主要的時間花費是請求的來回時間,而不在於帶寬大小。
固然,若是在HTTP2中,由於創建的是長鏈接,慢啓動可能就不存在了(不肯定,你們有不一樣的意見能夠提出)。
UDP( User Datagram Protocol,用戶數據報協議。
UDP 的主要功能和亮點並不在於它引入了什麼特性,而在於它忽略的那些特性:不保證消息交付,不保證交付順序,不跟蹤鏈接狀態,不須要擁塞控制。
咱們先來看一下UDP的數據包:
你們都知道IPV4地址是有限的,很快IPV4地址就快用完了,那怎麼解決這個問題呢?
固然,一個永久解決的辦法是IPV6,不過IPV6推出這麼多年了,好像尚未真正的普及。
不使用IPV6的話還有什麼解決辦法呢?
這個辦法就是NAT(Network Address Translators)。
NAT的原理是將局域網的IP和端口和NAT設備的IP和端口作個映射。
NAT內部維護着一張轉換表。這樣就能夠經過一個NAT的IP地址和不一樣的端口來鏈接衆多的局域網服務器。
那麼NAT有什麼問題呢?
NAT的問題在於,內部客戶端不知道本身外網IP地址,只知道內網IP地址。
若是是在UDP協議中,由於UDP是無狀態的,因此須要NAT來重寫每一個UDP分組中的源端口、地址,以及IP分組中的源IP地址。
若是客戶端是在應用程序內部將本身的IP地址告訴服務器,並想跟服務器創建鏈接,那麼確定是創建不了的。由於找不到客戶端的公網IP。
即便找到了公網IP,任何到達NAT設備外網IP的分組還必須有一個目標端口,並且NAT轉換表中也要有一個條目能夠將其轉換爲內部主機的IP地址和端口號。不然就可能出現下圖的鏈接失敗的問題。
怎麼解決呢?
第一種方式是使用STUN服務器。
STUN服務器是IP地址已知的服務器,客戶端要通訊以前,先去STUN服務器上面查詢一下本身的外網IP和端口,而後再使用這個外網IP和端口進行通訊。
但有時UDP包會被防火牆或者其餘的應用程序所阻擋。這個時候就可使用中繼器技術Traversal Using Relays around NAT (TURN) 。
雙方都將數據發送到中繼器server,由中繼器server來負責轉發數據。注意,這裏已經不是P2P了。
最後,咱們有一個集大成者的協議叫作ICE(Interactive Connectivity Establishment ):
它實際上就是直連,STUN和TURN的綜合體,能直連的時候就直連,不能直連就用STUN,不能用STUN就用TURN。
本文介紹了IP,TCP和UDP等協議和須要注意的一些事項,但願你們可以喜歡。
本文連接: http://www.flydean.com/network-and-performance/最通俗的解讀,最深入的乾貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!
歡迎關注個人公衆號:「程序那些事」,懂技術,更懂你!