HTTP協議 & DNS協議

博客主頁編程

http://restapi.amap.com 是個URL,叫做統一資源定位符。HTTP稱爲協議,restapi.amap.com是一個域名,表示互聯網上的一個位置。json

HTTP版本區別

HTTP/0.9 只支持get請求segmentfault

HTTP/1.0 增長版本號,請求頭,MIME,代理鏈接api

HTTP/1.1 默認持久鏈接,支持緩存,執行管道方式發送多個請求瀏覽器

HTTP請求的準備

瀏覽器會將restapi.amap.com這個域名發送給DNS服務器,讓它解析爲IP地址。那接下來是發送HTTP請求嗎?緩存

不是的,HTTP是基於TCP協議的,固然是要先創建TCP鏈接了,怎麼創建呢?Socket網絡編程 已經詳細講解了。服務器

目前使用的HTTP協議大部分都是1.1。在1.1的協議裏面,默認持久鏈接,也就是默認開啓了Keep-Alive的,這樣創建的TCP鏈接,就能夠在屢次請求中複用。網絡

學習了TCP以後,你應該知道,TCP的三次握手和四次揮手,仍是挺費勁的。若是好不容易創建了鏈接,而後就作了一點兒事情就結束了,有點兒浪費人力和物力。併發

HTTP請求的構建

創建了鏈接之後,瀏覽器就要發送HTTP的請求。app

請求的格式以下:

HTTP的報文大概分爲三大部分。第一部分是請求行,第二部分是請求的首部,第三部分纔是請求的正文實體

GET /v3/weather/weatherInfo?city=110101&key=13cb58f5884f9749287abbead9c658f2 HTTP/1.1
Host: restapi.amap.com

第一部分:請求行

在請求行中,URL就是請求的地址 ,版本爲HTTP 1.1。方法有幾種類型,最經常使用的類型就是GET。

GET就是去服務器獲取一些資源。另一種類型是POST,它須要主動告訴服務端一些信息,而非獲取,通常會將信息放在正文裏面,正文能夠有各類各樣的格式,常見的格式也是JSON。

還有一種類型叫PUT,就是向指定資源位置上傳最新內容。可是,HTTP的服務器每每是不容許上傳文件的,因此PUT和POST就都變成了要傳給服務器東西的方法。

再有一種常見的就是DELETE這個顧名思義就是用來刪除資源的。

第二部分:首部字段

首部是key: value,經過冒號分隔。這裏面,每每保存了一些很是重要的字段。

如,Accept-Charset,表示客戶端能夠接受的字符集。防止傳過來的是另外的字符集,從而致使出現亂碼。

如,Content-Type是指正文的格式。咱們進行POST的請求,若是正文是JSON,那麼咱們就應該將這個值設置爲JSON。

Content-Type: application/json

如,Content-Length是指正文的長度

Content-Length: 0

接下倆重點說一下的就是緩存

爲何要有緩存呢? 使用緩存能夠減小冗餘的數據傳輸,節省了網絡費用;還能夠緩解網絡瓶頸的問題,不須要更多的網絡寬帶就能更快的加載頁面,同時下降了對原始服務器的要求,服務器能夠更快的響應。

例如,我瀏覽一個商品的詳情,裏面有這個商品的價格、庫存、展現圖片、使用手冊等等。商品的展現圖片會保持較長時間不變,而庫存會根據用戶購買的狀況常常改變。若是圖片很是大,而庫存數很是小,若是咱們每次要更新數據的時候都要刷新整個頁面,對於服務器的壓力就會很大。

對於這種高併發場景下的系統,在真正的業務邏輯以前,都須要有個接入層,將這些靜態資源的請求攔在最外面。


對於靜態資源,有Vanish緩存層。當緩存過時的時候,纔會訪問真正的Tomcat應用集羣。

在HTTP頭裏面,Cache-control是用來控制緩存的。當客戶端發送的請求中包含max-age指令時,若是斷定緩存層中,資源的緩存時間數值比指定時間的數值小,那麼客戶端能夠接受緩存的資源;當指定max-age值爲0,那麼緩存層一般須要將請求轉發給應用集羣。包含no-cache指令時,無緩存指令(Cache-control: no-cache)。

另外,If-Modified-Since也是一個關於緩存的。也就是說,若是服務器的資源在某個時間以後更新了,那麼客戶端就應該下載最新的資源;若是沒有更新,服務端會返回「304 Not Modified」的響應,那客戶端就不用下載了,也會節省帶寬。同Last-Modified

If-None-Match 客戶端存取的該資源的檢驗值,在服務器上某個時段是惟一標識的。同ETag

到此爲止,咱們僅僅是拼湊起了HTTP請求的報文格式,接下來,瀏覽器會把它交給下一層傳輸層。怎麼交給傳輸層呢?其實也無非是用Socket這些東西,只不過用的瀏覽器裏,這些程序不須要你本身寫,有人已經幫你寫好了。

HTTP請求的發送

HTTP協議是基於TCP協議的,因此它使用面向鏈接的方式發送請求,經過stream二進制流的方式傳給對方。固然,到了TCP層,它會把二進制流變成一個的報文段發送給服務器。

在發送給每一個報文段的時候,都須要對方有一個迴應ACK,來保證報文可靠地到達了對方。若是沒有迴應,那麼TCP這一層會進行從新傳輸,直到能夠到達。同一個包有可能被傳了好屢次,可是HTTP這一層不須要知道這一點,由於是TCP這一層在埋頭苦幹。

TCP層發送每個報文的時候,都須要加上本身的地址(即源地址)和它想要去的地方(即目標地址),將這兩個信息放到IP頭裏面,交給IP層進行傳輸。

IP層須要查看目標地址和本身是不是在同一個局域網。若是是,就發送ARP協議來請求這個目標地址對應的MAC地址,而後將源MAC和目標MAC放入MAC頭,發送出去便可;若是不在同一個局域網,就須要發送到網關,還要須要發送ARP協議,來獲取網關的MAC地址,而後將源MAC和網關MAC放入MAC頭,發送出去。

網關收到包發現MAC符合,取出目標IP地址,根據路由協議找到下一跳的路由器,獲取下一跳路由器的MAC地址,將包發給下一跳路由器。

這樣路由器一跳一跳終於到達目標的局域網。這個時候,最後一跳的路由器可以發現,目標地址就在本身的某一個出口的局域網上。因而,在這個局域網上發送ARP,得到這個目標地址的MAC地址,將包發出去。

目標的機器發現MAC地址符合,就將包收起來;發現IP地址符合,根據IP頭中協議項,知道本身上一層是TCP協議,因而解析TCP的頭,裏面有序列號,須要看一看這個序列包是否是我要的,若是是就放入緩存中而後返回一個ACK,若是不是就丟棄。

TCP頭裏面還有端口號,HTTP的服務器正在監聽這個端口號。因而,目標機器天然知道是HTTP服務器這個進程想要這個包,因而將包發給HTTP服務器。HTTP服務器的進程看到,原來這個請求是要訪問一個網頁,因而就把這個網頁發給客戶端。

HTTP返回的構建

HTTP的返回報文也是有必定格式的。這也是基於HTTP 1.1的。

HTTP/1.1 200 OK
Server: Tengine
Date: Thu, 26 Dec 2019 06:52:14 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 252
Connection: close
X-Powered-By: ring/1.0.0
gsid: 011025248187157734313415200030229349471
sc: 0.006
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key,x-biz,x-info,platinfo,encr,enginever,gzipped,poiid

{"status":"1","count":"1","info":"OK","infocode":"10000","lives":[{"province":"北京","city":"東城區","adcode":"110101","weather":"晴","temperature":"2","winddirection":"西","windpower":"≤3","humidity":"23","reporttime":"2019-12-26 14:36:44"}]}

狀態碼會反應HTTP請求的結果。「200」意味着請求成功;而「404」,也就是「服務端沒法響應這個請求」

而後就是返回首部的key: value
其中Retry-After表示,告訴客戶端應該在多長時間之後再次嘗試一下。「503錯誤」是說「服務暫時再也不和這個值配合使用」。

在返回的頭部裏面也會有Content-Type,表示返回的是HTML,仍是JSON。

構造好了返回的HTTP報文,接下來就是把這個報文發送出去。仍是交給Socket去發送,仍是交給TCP層,讓TCP層將返回的HTML,也分紅一個個小的段,而且保證每一個段均可靠到達。

這些段加上TCP頭後會交給IP層,而後把剛纔的發送過程反向走一遍。雖然兩次不必定走相同的路徑,可是邏輯過程是同樣的,一直到達客戶端。

客戶端發現MAC地址符合、IP地址符合,因而就會交給TCP層。根據序列號看是否是本身要的報文段,若是是,則會根據TCP頭中的端口號,發給相應的進程。這個進程就是瀏覽器,瀏覽器做爲客戶端也在監聽某個端口。

當瀏覽器拿到了HTTP的報文。發現返回「200」,一切正常,因而就從正文中將HTML拿出來。HTML是一個標準的網頁格式。瀏覽器只要根據這個格式,展現出一個絢麗多彩的網頁。

這就是一個正常的HTTP請求和返回的完整過程。

DNS協議

若是要記得住網站的名稱,可是很難記住網站的IP地址,於是也須要一個地址簿,就是DNS服務器

因而可知,DNS在平常生活中多麼重要。每一個人上網,都須要訪問它,可是同時,這對它來說也是很是大的挑戰。一旦它出了故障,整個互聯網都將癱瘓。另外,上網的人分佈在全世界各地,若是你們都去同一個地方訪問某一臺服務器,時延將會很是大。於是,DNS服務器,必定要設置成高可用、高併發和分佈式的

  • 根DNS服務器 :返回頂級域DNS服務器的IP地址
  • 頂級域DNS服務器:返回權威DNS服務器的IP地址
  • 權威DNS服務器 :返回相應主機的IP地址

DNS解析流程

爲了提升DNS的解析性能,不少網絡都會就近部署DNS緩存服務器。因而,就有了如下的DNS解析流程。

  1. 電腦客戶端會發出一個DNS請求,問www.163.com的IP是啥啊,併發給本地域名服務器 (本地DNS)。那本地域名服務器 (本地DNS) 是什麼呢?若是是經過DHCP配置,本地DNS由你的網絡服務商(ISP),如電信、移動等自動分配,它一般就在你網絡服務商的某個機房。
  2. 本地DNS收到來自客戶端的請求。你能夠想象這臺服務器上緩存了一張域名與之對應IP地址的大表格。若是能找到 www.163.com,它直接就返回IP地址。若是沒有,本地DNS會去問它的根域名服務器:「老大,能告訴我www.163.com的IP地址嗎?」根域名服務器是最高層次的,全球共有13套。它不直接用於域名解析,但能指明一條道路。
  3. 根DNS收到來自本地DNS的請求,發現後綴是 .com,說:「哦,www.163.com啊,這個域名是由.com區域管理,我給你它的頂級域名服務器的地址,你去問問它吧。」
  4. 本地DNS轉向問頂級域名服務器:「老二,你能告訴我www.163.com的IP地址嗎?」頂級域名服務器就是大名鼎鼎的好比 .com、.net、 .org這些一級域名,它負責管理二級域名,好比 163.com,因此它能提供一條更清晰的方向。
  5. 頂級域名服務器說:「我給你負責 www.163.com 區域的權威DNS服務器的地址,你去問它應該能問到。」
  6. 本地DNS轉向問權威DNS服務器:「您好,www.163.com 對應的IP是啥呀?」163.com的權威DNS服務器,它是域名解析結果的原出處。爲啥叫權威呢?就是個人域名我作主。
  7. 權限DNS服務器查詢後將對應的IP地址X.X.X.X告訴本地DNS。
  8. 本地DNS再將IP地址返回客戶端,客戶端和目標創建鏈接。

若是個人文章對您有幫助,不妨點個贊鼓勵一下(^_^)

相關文章
相關標籤/搜索