前端日拱一卒D4——網絡基礎與HTTP

前言

餘爲前端菜鳥,感姿式水平匱乏,難觀前端之大局。遂決定循前端知識之脈絡,以興趣爲引,輔以幾分堅持,望於己能解惑致知、於同道能助力一二,豈不美哉。css

本系列代碼及文檔均在 此處html

網絡層級

20170516149490559398728.png

  • 實體層(物理層):鏈接計算機(光纖、電纜線、無線電波、雙絞線等)。前端

  • 連接層(數據鏈路層):肯定0 1的分組形式。nginx

    • 以太網協議git

      一組電信號組成一幀,一幀分爲head和data兩部分,head中包含接收方MAC地址信息,以廣播的方式向本網絡內全部計算機發送數據包,由接收方本身比對MAC地址判斷是否接收。github

  • 網絡層:主機到主機的通訊。web

    • 互聯網由許多子網絡組成,在同一子網中能夠經過MAC地址以廣播形式找到目標,可是不一樣子網廣播不過去,因此須要在網絡層引入新的地址用於查找子網絡,即網址。算法

    • IP協議chrome

      IPV4規定網絡地址由32個二進制位組成,以IP地址與子網掩碼相加是否相等判斷是否位於同一個子網絡。IP數據包放入到以太網數據包的data部分,IP數據包一樣包含head和data兩部分。瀏覽器

    • ARP協議

      經過IP地址獲取MAC地址(不在同一子網交由網關處理),在同一個子網絡中廣播發出數據包包含目標IP地址,MAC地址爲FF:FF:FF:FF:FF:FF目標主機接收到後比對成功後報告本身的MAC地址,因而獲取到了MAC地址,能夠把數據包發送到子網絡裏任一主機。

  • 傳輸層:端口到端口的通訊。(端口爲每一個使用網卡的程序的編號)

    • UDP協議

      數據包放入到IP數據包的data中,一樣由head和data組成,head主要定義發出端口和接收端口,data爲具體內容。

    • TCP協議

      有確認機制的UDP,每一個數據包須要確認,過程複雜,消耗更多的資源。

  • 應用層:規定應用程序的數據格式。(DHCP,DNS,HTTP,FTP,SSH等)

20170516149490921439572.png

用戶角度

  • 網絡通訊是主機間數據包交換,要交換數據須要知道雙方的MAC地址和IP地址。

  • 用戶能夠經過靜態IP和動態IP兩種方式實現網絡通訊配置。

    • 設置本機靜態IP、子網掩碼從而肯定本機所處子網絡,設置網關用於跨子網通訊,設置DNS服務器地址用於DNS解析。
    • 利用DHCP協議,以廣播形式向DHCP服務器獲取動態的IP地址。
  • 實例:訪問頁面。

    • 瀏覽器中輸入URL,從本地(瀏覽器->OS)DNS緩存中獲取目標服務器IP地址,本地沒有則向DNS服務器請求,獲取到IP地址後緩存到本地。
    • 判斷是否爲同一子網絡,是則數據包應包含本機和目標主機的MAC、IP地址,不然目標主機的MAC地址應改成網關MAC地址。
    • 組裝數據包,如上圖。
    • 創建TCP鏈接,經歷三次握手後在第三次將數據包發送到目標服務器,服務器取出完整的TCP數據包後作處理,定位資源,將資源複本寫到TCP套接字作出HTTP響應,而後藉由TCP協議再發送回來到客戶端。
    • 客戶端收到響應,進行頁面處理、展現。

HTTP

基礎

應用層協議,無狀態。

  • 請求/響應模型

    客戶端向服務端發送請求,服務端根據接收到的請求,處理後向客戶端返回響應信息。

  • url

    協議類型:[//[訪問資源須要的憑證信息@]服務器地址[:端口號]][/資源層級UNIX文件路徑]文件名[?查詢][#片斷ID]

    用於定位資源,輸入url->客戶端展現的過程再也不贅述

  • 請求/響應結構

    • 請求:請求行、請求頭、請求正文(只有POST有)
    • 響應:狀態行、響應頭、響應正文
    • 頭域:重點關注緩存相關,這裏不贅述

    get和post區別在於前者參數在url後,後者在請求正文;前者有大小限制,後者無,後者有請求體,前者無

    關於狀態碼,通常來講簡單記憶以下:1XX 可續發 2XX 成功 3XX 重定向 4XX 客戶端錯誤 5XX 服務端錯誤

HTTP1.1

  • 長鏈接

    // 請求頭、響應頭中包含
    Connection: keep-alive
    複製代碼

    1.1默認開啓長鏈接,使得鏈接在一段時間內維持開啓,後續請求可複用,減小創建鏈接的成本

  • 協議升級

    // 請求頭中包含
    Connection: Upgrade
    Upgrade: websocket
    複製代碼

    升級爲websocket協議,後續會談到

  • 緩存控制

    cache-rule

    • 1.0的expires -> 1.1的cache-control

      後者是相對時間,二者都存在時,之後者爲判斷過時依據(瀏覽器判斷)

    • Etag與Last-Modified

      若是上次返回頭中有Etag,則帶上if-none-match信息請求到服務端,服務端進行判斷Etag是否修改,選擇304/200

      若是上次返回頭中有Last-Modified,則帶上if-modified-since信息請求道服務端,服務端判斷是否失效,返回304/200

  • 痛點

    • 明文傳輸,不安全
    • header過大,且不少時候header變化不大,資源浪費
    • keep-alive給服務端帶來性能問題
  • 需優化點

    • 帶寬
      • pay more
    • 延遲
      • DNS解析:解決:預解析與緩存。
      • 創建鏈接消耗:基於TCP,每次創建鏈接都須要經歷三次握手,最快也要在第三次才能將報文發送到服務端。解決:keep-alive/HTTP2
      • 瀏覽器阻塞:因爲瀏覽器單域名下最大鏈接限制(6個),達到限制後會致使後續請求阻塞,解決:將域名分區,提升並行資源下載能力;合併資源,減小請求個數。

HTTPS

圖解

HTTPS運行在SSL/TLS上,SSL/TLS運行在TCP上,全部傳輸內容都是須要加密的,能夠有效防劫持

握手階段:

  • 客戶端給出協議版本、客戶端生成的隨機數、支持的加密方法
  • 服務端收到後確認加密方法,返回數字證書,以及一個服務端生成的隨機數
  • 客戶端確認證書有效,生成一個隨機數,用證書彙總的公鑰加密隨機數,發送給服務端
  • 服務端使用私鑰得到客戶端發送的隨機數
  • 根據約定的加密算法,使用前面的三個隨機數生成會話密鑰,用來加密後續整個會話過程

加密解密

  • 公鑰和私鑰只用於加密/解密 對話密鑰(非對稱)
  • 安全與否取決於三個隨機數中的第三個可否被破解

對稱加密/非對稱加密

  • 使用一對密鑰,公鑰用來加密,私鑰不公開,用於解密,慢,可是更安全 ----> 非對稱加密
  • 密鑰在網絡中傳輸,快可是不安全 ----> 對稱加密
  • 解決:用非對稱加密的公鑰加密對稱加密的密鑰,接收方用私鑰解密獲得對稱密鑰,用於加密信息(減小複雜度,下降服務器壓力)

升級至HTTPS

  • github免費的github pages用來搭建我的博客很是方便,感興趣的能夠參考這裏

    在項目設置下選擇開啓HTTPS便可

    小綠鎖很醒目

  • 我的站點升級HTTPS

    • 從域名服務商獲取免費的SSL證書

      按照流程填寫

    • 下載證書到服務器(個人是一年免費的谷歌gce)

    • 修改nginx配置

      server {
          listen 80;
          server_name pandora.derekz.cn;
          # 重定向到https
          rewrite ^(.*)$  https://$host$1 permanent;
      
          location / {
              root html;
              index index.html index.htm;
          }
      }
      server {
          # 順便換http2吧
          listen 443 ssl http2;
          server_name pandora.derekz.cn;
          root html;
          index index.html index.htm;
      
          # 你的證書路徑
          ssl_certificate   /etc/nginx/cert/xxxxxxx.pem;
          ssl_certificate_key  /etc/nginx/cert/xxxxxxx.key;
      
          ssl_session_timeout 5m;
          ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
          ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
          ssl_prefer_server_ciphers on;
      }
      複製代碼
    • 重啓nginx,稍稍等待訪問我的網站

HTTP2

SPDY

SPDY與HTTP2區別在於前者強制使用SSL傳輸協議,以及二者在首部算法上有所區別,SPDY出現於HTTP2前,特色與HTTP2相似:多路複用、服務器推送、頭部壓縮等。這裏暫不討論。

核心——二進制分幀

  • HTTP2採用徹底二進制的格式傳輸數據。二進制數據在網絡中傳輸單位通常爲幀
  • 一個幀包含有:類型Type、長度Length、標記Flag、流標識Stream和Frame payload(幀有效載荷)
  • 多個幀造成幀的傳輸網絡流,能夠認爲HTTP2是流式傳輸。

  • 不改變HTTP的語義,方法、首部、動詞都不受影響
  • 在應用層(HTTP2.0)和傳輸層(TCP)之間多了一個二進制分幀層
  • 將請求的內容分割爲幀,頭部信息放入headers幀,body放入data幀
  • HTTP2.0全部的通訊都在一個鏈接上完成,每一個數據流以消息形式發送,一個消息包含一個或多個幀,能夠亂序,到達目的地後根據幀首部的流標識符重組

首部壓縮

  • 客戶端和服務器端使用「首部表」來跟蹤和存儲以前發送的鍵-值對
  • 若是首部不發生變化,那麼首部0開銷,此時首部自動使用以前請求的首部
  • 若是發生變化,只須要將變化的部分填入首部,同時更新兩端維護的首部表便可
  • 因而,並不會有分幀後多加了不少首部幀帶來的性能問題,反而提高了性能
  • 合併資源減小請求並不適用與HTTP2,由於都在一個鏈接上

雙向並行

不須要域名分區,由於不限制,並且能夠雙向並行多個請求/響應

HTTP2的多路複用與1.x的keep-alive本質上有區別,一個位於傳輸層,一個位於應用層,且後者是串行的,前者容許多個文件傳輸幀在圖個TCP鏈接中同時流式傳輸

服務端推送

location / {
  root   /usr/share/nginx/html;
  index  index.html index.htm;
  http2_push /style.css;
  http2_push /example.png;
}
複製代碼

http2_push字段,只請求了/index.html 卻返回了style.css等額外數據。待研究

遷移HTTP2

細心的小夥伴也許發現了上面的nginx conf文件內有這麼一行

listen 443 ssl http2;
複製代碼

從HTTPS遷移到HTTP2很是簡單,只須要修改nginx配置便可,最後打開chrome能夠看到http2的鏈接狀況

思考

咱們說一個網頁的性能多好,最直接的一個表現是從enter敲下到頁面展現花的時間多短,也就是咱們追求的低延遲高帶寬。帶寬隨着網絡基礎建設不斷提升,因此性能瓶頸主要在於低延遲的難實現。

想一想看,咱們又要DNS解析,又要創建鏈接,還要加密解密,歷經千難萬險才能把請求信息送到服務器上。完了之後那一頭的人還得禮尚往來,這之間每一個步驟都是咱們實現低延遲的障礙,也是咱們優化的方向。

好比DNS預解析、HTTP2的多路複用使用一條鏈接、頭部壓縮、對稱加密+非對稱加密、緩存策略等等。理解這樣一個過程之後,要怎麼作就得實際動手處理問題中積累經驗啦。

雖發表於此,卻畢竟爲一人之言,又是每日學有所得之筆記,內容未必詳實,看官老爺們還望海涵。

相關文章
相關標籤/搜索