1. 程式人生 > 其它 >6. Lab: Multithreading

6. Lab: Multithreading

鍵入網址再按下回車,後面究竟發生了什麼?

  1. 如果連結地址是域名開頭的,瀏覽器會開始 DNS 解析動作。解析優先順序依次為:瀏覽器快取 > 作業系統快取 > 本機 hosts 檔案 > “野生 DNS 伺服器” >核心 DNS 伺服器( 根級 DNS > 頂級 DNS > 權威 DNS) ;將域名解析為正確的 ip 地址之後,通過三次握手與伺服器建立 tcp/ip 連線;瀏覽器傳送請求報文,伺服器接收並處理請求,返回響應報文,瀏覽器開始解析 html 文件,在這過程中又會發起一些 http 請求,進行圖片、css、js 等靜態資源的獲取,以及 ajax 請求獲取 json 資料。同時,瀏覽器相關引擎開始繪製 dom 檢視,執行 js 指令碼,完成頁面的初始化直到所有程式碼執行完畢。

  2. 如 1 中所說 DNS 解析順序,當請求 DNS 伺服器進行域名解析時,發現沒有找到對應的 ip,會導致解析失敗,無法建立 tcp/ip 連結,導致瀏覽器建立連線時間過長,最終建立連線失敗,瀏覽器停止建立連線動作。

HTTP 是什麼?有什麼特點?

超文字傳輸協議。HTTP 是一個在計算機世界裡專門在兩點之間傳輸文字、圖片、音訊、視訊等超文字資料的約定和規範。

  1. 支援客戶/伺服器模式。

  2. 簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有 GET、HEAD、
    POST。

  3. 靈活:HTTP 允許傳輸任意型別的資料物件。

  4. 無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的
    應答後,即斷開連線。採用這種方式可以節省傳輸時間。

  5. 無狀態:HTTP 協議是無狀態協議。

HTTP 請求頭和響應頭

請求頭:請求行、訊息報頭、請求正文
響應頭:狀態行、訊息報頭、響應正文

HTTP 請求方法瞭解哪些?

GET 和 POST 的區別

  • get 提交的資料會放在 URL 之後,並且請求引數會被完整的保留在瀏覽器的記錄裡,由於引數直接暴露在 URL 中,可能會存在安全問題,因此往往用於獲取資源資訊。而 post 引數放在請求主體中,並且引數不會被保留,相比 get 方法,post 方法更安全,主要用於修改伺服器上的資源。

  • get 請求只支援 URL 編碼,post 請求支援多種編碼格式。

  • get 只支援 ASCII 字元格式的引數,而 post 方法沒有限制。

  • get 提交的資料大小有限制(這裡所說的限制是針對瀏覽器而言的),而 post 方法提交的資料沒限制

  • get 方式需要使用 Request.QueryString 來取得變數的值,而 post 方式通過 Request.Form 來獲取。

  • get 方法產生一個 TCP 資料包,post 方法產生兩個(並不是所有的瀏覽器中都產生兩個)

HTTP 與 HTTPs 的工作方式【建立連線的過程】

HTTP

HTTP(Hyper Text Transfer Protocol: 超文字傳輸協議) 是一種簡單的請求 - 響應協議,被用於在 Web 瀏覽器和網站伺服器之間傳遞訊息。HTTP 使用 TCP(而不是 UDP)作為它的支撐運輸層協議。其預設工作在 TCP 協議 80 埠,HTTP 客戶機發起一個與伺服器的 TCP 連線,一旦連線建立,瀏覽器和伺服器程序就可以通過套接字介面訪問 TCP。客戶機從套接字介面傳送 HTTP 請求報文和接收 HTTP 響應報文。類似地,伺服器也是從套接字介面接收 HTTP 請求報文和傳送 HTTP 響應報文。其通訊內容以明文的方式傳送,不通過任何方式的資料加密。當通訊結束時,客戶端與伺服器關閉連線。

HTTPS

HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)是以安全為目標的 HTTP 協議,在 HTTP 的基礎上通過傳輸加密和身份認證的方式保證了傳輸過程的安全性。其工作流程如下:

① 客戶端發起一個 HTTPS 請求,並連線到伺服器的 443 埠,傳送的資訊主要包括自身所支援的演算法列表和金鑰長度等;

② 服務端將自身所支援的所有加密演算法與客戶端的演算法列表進行對比並選擇一種支援的加密演算法,然後將它和其它金鑰元件一同傳送給客戶端。

③ 伺服器向客戶端傳送一個包含數字證書的報文,該數字證書中包含證書的頒發機構、過期時間、服務端的公鑰等資訊。

④ 最後服務端傳送一個完成報文通知客戶端 SSL 的第一階段已經協商完成。

⑤ SSL 第一次協商完成後,客戶端傳送一個迴應報文,報文中包含一個客戶端生成的隨機密碼串,稱為 pre_master_secret,並且該報文是經過證書中的公鑰加密過的。

⑥ 緊接著客戶端會發送一個報文提示服務端在此之後的報文是採用 pre_master_secret 加密的。

⑦ 客戶端向服務端傳送一個 finish 報文,這次握手中包含第一次握手至今所有報文的整體校驗值,最終協商是否完成取決於服務端能否成功解密。

⑧ 服務端同樣傳送與第 ⑥ 步中相同作用的報文,已讓客戶端進行確認,最後傳送 finish 報文告訴客戶端自己能夠正確解密報文。

當服務端和客戶端的 finish 報文交換完成之後,SSL 連線就算建立完成了,之後就進行和 HTTP 相同的通訊過程,唯一不同的是在 HTTP 通訊過程中並不是採用明文傳輸,而是採用對稱加密的方式,其中對稱金鑰已經在 SSL 的建立過程中協商好了。

HTTPS 和 HTTP 的區別

  • HTTP 協議以明文方式傳送內容,資料都是未加密的,安全性較差。HTTPS 資料傳輸過程是加密的,安全性較好。
  • HTTP 和 HTTPS 使用的是完全不同的連線方式,用的埠也不一樣,前者是 80 埠,後者是 443 埠。
  • HTTPS 協議需要到數字認證機構(Certificate Authority, CA)申請證書,一般需要一定的費用。
  • HTTP 頁面響應比 HTTPS 快,主要因為 HTTP 使用 3 次握手建立連線,客戶端和伺服器需要握手 3 次,而 HTTPS 除了 TCP 的 3 次握手,還需要經歷一個 SSL 協商過程。

HTTP 是不儲存狀態的協議,如何儲存使用者狀態

我們知道,假如某個特定的客戶機在短時間內兩次請求同一個物件,伺服器並不會因為剛剛為該使用者提供了該物件就不再做出反應,而是重新發送該物件,就像該伺服器已經完全忘記不久之前所做過的是一樣。因為一個 HTTP 伺服器並不儲存關於客戶機的任何資訊,所以我們說 HTTP 是一個無狀態協議。

通常有兩種解決方案:

① 基於 Session 實現的會話保持

在客戶端第一次向伺服器傳送 HTTP 請求後,伺服器會建立一個 Session 物件並將客戶端的身份資訊以鍵值對的形式儲存下來,然後分配一個會話標識(SessionId)給客戶端,這個會話標識一般儲存在客戶端 Cookie 中,之後每次該瀏覽器傳送 HTTP 請求都會帶上 Cookie 中的 SessionId 到伺服器,伺服器根據會話標識就可以將之前的狀態資訊與會話聯絡起來,從而實現會話保持。

優點:安全性高,因為狀態資訊儲存在伺服器端。

缺點:由於大型網站往往採用的是分散式伺服器,瀏覽器傳送的 HTTP 請求一般要先通過負載均衡器才能到達具體的後臺伺服器,倘若同一個瀏覽器兩次 HTTP 請求分別落在不同的伺服器上時,基於 Session 的方法就不能實現會話保持了。

【解決方法:採用中介軟體,例如 Redis,我們通過將 Session 的資訊儲存在 Redis 中,使得每個伺服器都可以訪問到之前的狀態資訊】

② 基於 Cookie 實現的會話保持

當伺服器傳送響應訊息時,在 HTTP 響應頭中設定 Set-Cookie 欄位,用來儲存客戶端的狀態資訊。客戶端解析出 HTTP 響應頭中的欄位資訊,並根據其生命週期建立不同的 Cookie,這樣一來每次瀏覽器傳送 HTTP 請求的時候都會帶上 Cookie 欄位,從而實現狀態保持。基於 Cookie 的會話保持與基於 Session 實現的會話保持最主要的區別是前者完全將會話狀態資訊儲存在瀏覽器 Cookie 中。

優點:伺服器不用儲存狀態資訊, 減輕伺服器儲存壓力,同時便於服務端做水平拓展。

缺點:該方式不夠安全,因為狀態資訊儲存在客戶端,這意味著不能在會話中儲存機密資料。除此之外,瀏覽器每次發起 HTTP 請求時都需要傳送額外的 Cookie 到伺服器端,會佔用更多頻寬。

拓展:Cookie 被禁用了怎麼辦?

若遇到 Cookie 被禁用的情況,則可以通過重寫 URL 的方式將會話標識放在 URL 的引數裡,也可以實現會話保持。

什麼是 Cookie ?

  • HTTP 是無狀態的協議(對於事務處理沒有記憶能力,每次客戶端和服務端會話完成時,服務端不會儲存任何會話資訊):每個請求都是完全獨立的,服務端無法確認當前訪問者的身份資訊,無法分辨上一次的請求傳送者和這一次的傳送者是不是同一個人。所以伺服器與瀏覽器為了進行會話跟蹤(知道是誰在訪問我),就必須主動的去維護一個狀態,這個狀態用於告知服務端前後兩個請求是否來自同一瀏覽器。而這個狀態需要通過 cookie 或者 session 去實現。

  • cookie 儲存在客戶端: cookie 是伺服器傳送到使用者瀏覽器並儲存在本地的一小塊資料,它會在瀏覽器下次向同一伺服器再發起請求時被攜帶併發送到伺服器上。

  • cookie 是不可跨域的: 每個 cookie 都會繫結單一的域名,無法在別的域名下獲取使用,一級域名和二級域名之間是允許共享使用的(靠的是 domain)。

什麼是 Session ?

  • session 是另一種記錄伺服器和客戶端會話狀態的機制
  • session 是基於 cookie 實現的,session 儲存在伺服器端,sessionId 會被儲存到客戶端的 cookie 中。

SessionID 是連線 Cookie 和 Session 的一道橋樑,大部分系統也是根據此原理來驗證使用者登入狀態。

Cookie 和 Session 的區別?

  • 安全性: Session 比 Cookie 安全,Session 是儲存在伺服器端的,Cookie 是儲存在客戶端的。
  • 存取值的型別不同:Cookie 只支援存字串資料,想要設定其他型別的資料,需要將其轉換成字串,Session 可以存任意資料型別。
  • 有效期不同: Cookie 可設定為長時間保持,比如我們經常使用的預設登入功能,Session 一般失效時間較短,客戶端關閉(預設情況下)或者 Session 超時都會失效。
  • 儲存大小不同: 單個 Cookie 儲存的資料不能超過 4K,Session 可儲存資料遠高於 Cookie,但是當訪問量過多,會佔用過多的伺服器資源。

什麼是 Token ?

  • 訪問資源介面(API)時所需要的資源憑證.

  • 每一次請求都需要攜帶 token,需要把 token 放到 HTTP 的 Header 裡

  • 基於 token 的使用者認證是一種服務端無狀態的認證方式,服務端不用存放 token 資料。用解析 token 的計算時間換取 session 的儲存空間,從而減輕伺服器的壓力,減少頻繁的查詢資料庫

  • token 的身份驗證流程

Token 和 Session 的區別?

  • Session 是一種記錄伺服器和客戶端會話狀態的機制,使服務端有狀態化,可以記錄會話資訊。而 Token 是令牌,訪問資源介面(API)時所需要的資源憑證。Token 使服務端無狀態化,不會儲存會話資訊。

  • Session 和 Token 並不矛盾,作為身份認證 Token 安全性比 Session 好,因為每一個請求都有簽名還能防止監聽以及重放攻擊,而 Session 就必須依賴鏈路層來保障通訊安全了。如果你需要實現有狀態的會話,仍然可以增加 Session 來在伺服器端儲存一些狀態。

  • 所謂 Session 認證只是簡單的把 User 資訊儲存到 Session 裡,因為 SessionID 的不可預測性,暫且認為是安全的。而 Token ,如果指的是 OAuth Token 或類似的機制的話,提供的是認證 和授權 ,認證是針對使用者,授權是針對 App 。其目的是讓某 App 有權利訪問某使用者的資訊。這裡的 Token 是唯一的。不可以轉移到其它 App 上,也不可以轉到其它使用者上。Session 只提供一種簡單的認證,即只要有此 SessionID ,即認為有此 User 的全部權利。是需要嚴格保密的,這個資料應該只儲存在站方,不應該共享給其它網站或者第三方 App。所以簡單來說:如果你的使用者資料可能需要和第三方共享,或者允許第三方呼叫 API 介面,用 Token 。如果永遠只是自己的網站,自己的 App,用什麼就無所謂了。

HTTP 狀態碼有哪些?

DNS 的作用

DNS

DNS(Domain Name System)是域名系統的英文縮寫,是一種組織成域層次結構的計算機和網路服務命名系統,用於 TCP/IP 網路。

DNS 的作用

通常我們有兩種方式識別主機:通過主機名或者 IP 地址。人們喜歡便於記憶的主機名錶示,而路由器則喜歡定長的、有著層次結構的 IP 地址。為了滿足這些不同的偏好,我們就需要一種能夠進行主機名到 IP 地址轉換的目錄服務,域名系統作為將域名和 IP 地址相互對映的一個分散式資料庫,能夠使人更方便地訪問網際網路。

URI(統一資源識別符號)和 URL(統一資源定位符)之間的區別

從定義即可看出,URL 是 URI 的一個子集。只要能唯一標識資源的就是 URI,在 URI 的基礎上給出其資源的訪問方式的就是 URL。

TCP 三次握手和四次揮手

三次握手是 TCP 連線的建立過程。在握手之前,主動開啟連線的客戶端結束 CLOSE 階段,被動開啟的伺服器也結束 CLOSE 階段,並進入 LISTEN 階段。隨後進入三次握手階段:

① 首先客戶端向伺服器傳送一個 SYN 包,並等待伺服器確認,其中:

  • 標誌位為 SYN,表示請求建立連線;
  • 序號為 Seq = x(x 一般取隨機數);
  • 隨後客戶端進入 SYN-SENT 階段。

② 伺服器接收到客戶端發來的 SYN 包後,對該包進行確認後結束 LISTEN 階段,並返回一段 TCP 報文,其中:

  • 標誌位為 SYN 和 ACK,表示確認客戶端的報文 Seq 序號有效,伺服器能正常接收客戶端傳送的資料,並同意建立新連線;
  • 序號為 Seq = y;
  • 確認號為 Ack = x + 1,表示收到客戶端的序號 Seq 並將其值加 1 作為自己確認號 Ack 的值,隨後伺服器端進入 SYN-RECV 階段。

③ 客戶端接收到傳送的 SYN + ACK 包後,明確了從客戶端到伺服器的資料傳輸是正常的,從而結束 SYN-SENT 階段。並返回最後一段報文。其中:

  • 標誌位為 ACK,表示確認收到伺服器端同意連線的訊號;
  • 序號為 Seq = x + 1,表示收到伺服器端的確認號 Ack,並將其值作為自己的序號值;
  • 確認號為 Ack= y + 1,表示收到伺服器端序號 seq,並將其值加 1 作為自己的確認號 Ack 的值。
  • 隨後客戶端進入 ESTABLISHED。
  • 當伺服器端收到來自客戶端確認收到伺服器資料的報文後,得知從伺服器到客戶端的資料傳輸是正常的,從而結束 SYN-RECV 階段,進入 ESTABLISHED 階段,從而完成三次握手。

四次揮手即 TCP 連線的釋放,這裡假設客戶端主動釋放連線。在揮手之前主動釋放連線的客戶端結束 ESTABLISHED 階段,隨後開始四次揮手:

① 首先客戶端向伺服器傳送一段 TCP 報文表明其想要釋放 TCP 連線,其中:

  • 標記位為 FIN,表示請求釋放連線;
  • 序號為 Seq = u;
  • 隨後客戶端進入 FIN-WAIT-1 階段,即半關閉階段,並且停止向服務端傳送通訊資料。

② 伺服器接收到客戶端請求斷開連線的 FIN 報文後,結束 ESTABLISHED 階段,進入 CLOSE-WAIT 階段並返回一段 TCP 報文,其中:

  • 標記位為 ACK,表示接收到客戶端釋放連線的請求;
  • 序號為 Seq = v;
  • 確認號為 Ack = u + 1,表示是在收到客戶端報文的基礎上,將其序號值加 1 作為本段報文確認號 Ack 的值;
  • 隨後伺服器開始準備釋放伺服器端到客戶端方向上的連線。
  • 客戶端收到伺服器傳送過來的 TCP 報文後,確認伺服器已經收到了客戶端連線釋放的請求,隨後客戶端結束 FIN-WAIT-1 階段,進入 FIN-WAIT-2 階段。

③ 伺服器端在發出 ACK 確認報文後,伺服器端會將遺留的待傳資料傳送給客戶端,待傳輸完成後即經過 CLOSE-WAIT 階段,便做好了釋放伺服器端到客戶端的連線準備,再次向客戶端發出一段 TCP 報文,其中:

  • 標記位為 FIN 和 ACK,表示已經準備好釋放連線了;
  • 序號為 Seq = w;
  • 確認號 Ack = u + 1,表示是在收到客戶端報文的基礎上,將其序號 Seq 的值加 1 作為本段報文確認號 Ack 的值。
  • 隨後伺服器端結束 CLOSE-WAIT 階段,進入 LAST-ACK 階段。並且停止向客戶端傳送資料。

④ 客戶端收到從伺服器發來的 TCP 報文,確認了伺服器已經做好釋放連線的準備,於是結束 FIN-WAIT-2 階段,進入 TIME-WAIT 階段,並向伺服器傳送一段報文,其中:

  • 標記位為 ACK,表示接收到伺服器準備好釋放連線的訊號;
  • 序號為 Seq= u + 1,表示是在已收到伺服器報文的基礎上,將其確認號 Ack 值作為本段序號的值;
  • 確認號為 Ack= w + 1,表示是在收到了伺服器報文的基礎上,將其序號 Seq 的值作為本段報文確認號的值。

隨後客戶端開始在 TIME-WAIT 階段等待 2 MSL。伺服器端收到從客戶端發出的 TCP 報文之後結束 LAST-ACK 階段,進入 CLOSED 階段。由此正式確認關閉伺服器端到客戶端方向上的連線。客戶端等待完 2 MSL 之後,結束 TIME-WAIT 階段,進入 CLOSED 階段,由此完成「四次揮手」。