前言:
本文作為解決如何通過 Golang 來編寫 Web 應用這個問題的前瞻,對 Golang 中的 Web 基礎部分進行一個簡單的介紹。目前 Go 擁有成熟的 Http 處理包,所以我們去編寫一個做任何事情的動態(tài) Web 程序應該是很輕松的,接下來我們就去學習了解一些關于 Web 的相關基礎,了解一些概念,以及 Golang 是如何運行一個 Web 程序的。
文章預計分為四個部分逐步更新
2023-04-13 星期四 一更 全文共計約 3800 字 閱讀大約花費 5 分鐘
2023-04-14 星期五 二更(兩篇) 全文共計約 2000 字 閱讀大概花費 4 分鐘
2023-04-14 星期五 三更 全文共計約 2000 字 閱讀大概花費 5 分鐘
文章目錄:
- Web 的工作方式
- 用 Go 搭建一個最簡單的 Web 服務
- 了解 Golang 運行 web 的原理
- Golang http 包詳解(源碼剖析)
正文:
Web 的工作方式
-
了解當你訪問一個網頁時,背后是如何運作的,發(fā)生了一些什么?
其實當你輸入網址(URL)并按下回車之后,你的瀏覽器相當于扮演了 客戶端 的角色,首先你的瀏覽器會去請求 DNS 服務器進行域名解析,將你輸入的 URL 地址 轉化為對應的 ip 地址,通過 ip 地址 我們就可以找到對應的服務器位置,從而進行 TCP 連接。
連接之后,你的瀏覽器會發(fā)送 HTTP 請求 (Request)包,服務區(qū)收到請求包之后開始從響應處理請求包,調用自身的服務,并返回 HTTP 響應 (Response)包。
客戶端收到了來自服務端的響應之后開始渲染這個響應包里的主體(body),等收到了全部的內容應答后,就會斷開與服務器的 TCP 連接 (這里先討論一般情況)
如圖??
而一個 Web 服務器也被稱作 HTTP 服務器, 它通過 http 協(xié)議與客戶端通信。這個客戶端通常是指 Web 瀏覽器
所以 Web 服務器的工作原理可以簡單的總結為:
- 客戶端通過 TCP/IP 協(xié)議建立與服務器的 TCP 連接
- 客戶端向服務器發(fā)送 HTTP 協(xié)議請求包,請求服務器里的資源文檔
- 服務器向客戶機發(fā)送 HTTP 協(xié)議應答包, 如果請求的資源包含有其他動態(tài)語言的內容,服務器就會調用動態(tài)語言的解析引擎負責處理這些動態(tài)內容,并將處理得到的數據返回給客戶端
- 客戶端與服務端斷開連接??蛻舳碎_始解釋收到的 HTML 文檔,在客戶端屏幕上渲染圖形結果
以上步驟實現了一個 最簡單的 HTTP 事務,在上述情況中,客戶端與服務端的通信非持久連接,發(fā)送接收應答后就斷開(這里暫時不討論 http 1.1 之后的持久連接、后文會有專門說明)
-
URL 和 DNS 解析
剛剛我們提到了 URL,它可以用來輸入訪問網頁,那具體 URL 是個什么東西呢?
URL 是 Uniform Resource Locator“統(tǒng)一資源定位符” 的英文縮寫
基本格式如下圖??
而 DNS 則是 Domain Name System “域名系統(tǒng)” 的英文縮寫,它是一種組織成 域層次結構的計算機和網絡服務命名系統(tǒng),它用于 TCP/IP 網絡,它從事 將主機名 或者 域名轉換為實際 IP 地址的工作??梢园阉斫獬?URL 的“翻譯官”
工作原理如下圖??
我們來詳細地解釋一下 關于 DNS 的工作原理:
- 我們以 www.google.com 為例,在瀏覽器地址欄輸入該域名,操作系統(tǒng)會首先檢查自己的 hosts 文件中是否存在這個網址的映射關系,如果有,就可以直接調用這個 IP 地址的映射,完成域名解析
- 其次如果 hosts 里沒有這個域名的映射,則查找本地 DNS 解析器緩存,看里面有沒有這個網址的映射關系,如果有也直接調用
- 如果 hosts 和 本地 DNS 解析器緩存都沒有,就會先去找 TCP/IP 參數中設置的首選 DNS 服務器,我們可以把他叫做 本地 DNS 服務器,此服務器收到查詢需求時,如果要查詢的域名,包含在本地配置區(qū)域的資源中,就將解析結果返回給客戶端,完成域名解析,該解析具有權威性
- 如果要查詢的域名,本地 DNS 服務器配置區(qū)域資源沒有,但是該服務器卻緩存了此網址的映射關系,則也可以調用完成解析,但是該解析不具有權威性
- 如果本地 DNS 服務器本地區(qū)域資源文件以及緩存都沒有該映射,則根據本地 DNS 服務器的設置(是否設置轉發(fā)器)進行查詢,如果未用轉發(fā)模式, 本地DNS 就把請求發(fā)送至 “根 DNS 服務器” ,“根 DNS 服務器”收到請求后會判斷這個域名是誰來授權管理(本例子為.com),并會返回一個負責該頂級域名服務器的一個 IP。本地 DNS 服務器 收到 IP 信息后,將會聯(lián)系 負責管理 .com 域的這臺服務器。這臺服務器收到請求后,如果自己無法解析,它就會找管理 .com 域的下一級 DNS 服務器地址(這里是 google.com)并把它的 IP 給本地 DNS 服務器。當本地 DNS 服務器收到這個地址后,就會找 google.com 域服務器,重復上面的操作,進行查詢,直到找到(www.goole,com)為止
- 如果是轉發(fā)模式,則此 DNS 服務器就會把請求轉發(fā)至上一級 DNS 服務器,由上一級服務器進行解析,上一級如果不能解析,就找根服務器,或者轉發(fā)請求給上上級服務器,如此循環(huán),直到找到(www.goole,com)為止
無論是轉發(fā)模式還是非轉發(fā)模式,是轉發(fā)給上一級還是直接找根 DNS ,最后都是把 結果返回給 本地 DNS 服務器,由此 DNS服務器再返回給 我們的瀏覽器(客戶端)
流程圖如下??
基于上面的步驟,瀏覽器最終通過 DNS 服務器獲得的是 IP 地址,所以瀏覽器(客戶端)發(fā)起請求的時候是通過 IP 地址 來和 服務器 進行信息通信的
-
HTTP 協(xié)議詳解
HTTP 協(xié)議當然是 Web 服務器工作的核心,所以我們接下來具體詳細地了解清楚一下 HTTP 協(xié)議是怎么發(fā)揮作用的
-
HTTP 協(xié)議 是一種能讓 Web 服務器與瀏覽器(客戶端)通過 Internet 進行發(fā)送和接受數據 動作 的一個協(xié)議,它建立在 TCP 協(xié)議之上,一般會采用 TCP 的 80 端口。它是一個標準的 “請求-響應協(xié)議” 即 客戶端發(fā)出請求,服務端收到請求返回響應。
-
在 HTTP 協(xié)議中,客戶端總是要通過建立一個連接與發(fā)送一個 HTTP 請求來發(fā)起一個事務。而服務器不能主動去與客戶端聯(lián)系,也不能給客戶端發(fā)出一個回調連接,只能被動監(jiān)聽。
-
客戶端與服務端都可以自行提前中斷一個連接,例如,當瀏覽器下載一個文件時,你可以隨時通過點擊“暫?!卑粹o來中斷文件的下載,關閉與服務器的 HTTP 連接。
-
HTTP 協(xié)議是無狀態(tài)的,同一個客戶端的這一次請求與上次請求之間沒有對應關系,對 HTTP 服務器來說,它并不知道這兩個請求是否來自同一個客戶端。當然對于需要解決這個問題的情況我們可以使用 "Cookie"機制來維護連接的可持續(xù)狀態(tài)
-
正因為 HTTP 協(xié)議是建立在 TCP 協(xié)議之上的,所以 TCP 攻擊一樣會影響 HTTP 的通信,例如常見的針對 TCP 的攻擊:SYN Flood (比較流行的一種 Dos 拒絕服務攻擊 和 Ddos 分布式拒絕服務攻擊)就是通過利用 TCP 協(xié)議的缺陷,發(fā)送了大量的偽造 TCP 連接請求從而使得被攻擊的服務器資源耗盡(CPU 滿負荷或者內存不足)
接下來我們分別看看 HTTP 協(xié)議的 請求包和響應包
HTTP 請求包 (瀏覽器/客戶端 信息)
我們可以使用 F12 查看一些內容,例如 Request 包的結構:
Request 包分為三部分,第一部分叫 Request line (請求行),第二部分是 Request header (請求頭),第三部分是 body(主體),header 和 body 之間會有個空行隔開
請求包的實例圖??
HTTP 協(xié)議定義了很多與服務器交互的請求方法,最基礎的四種是:GET\POST\PUT\DELETE,一個 URL 地址用于描述一個網絡上的請求資源,而 HTTP 中的這四個操作就分別對應對這個資源的查改增刪4個操作
這四個操作中最熟悉和常用的是 GET 和 POST 。
GET 一般用于獲取/查詢資源信息
POST 一般用于更新資源信息
GET 與 POST 的區(qū)別:
- GET 方法提交的數據會放在 URL 后面,使用 ? 分割 URL 和 傳輸的數據,參數之間以 & 相連
- POST 方法則是把提交的數據放在 HTTP 包的 body 中
- GET能提交的數據大小會因為瀏覽器對于 URL 的長度限制而有所限制
- POST 方法提交的數據不會有限制
- GET 方法提交數據會帶來某些安全問題,例如:在用戶的登錄界面,如果使用 GET 方法提交數據,用戶的賬號和密碼就會出現在 URL 上面,如果頁面被緩存或者其他人可以訪問機器,就可以額從歷史記錄中獲得該用戶的賬號和密碼!
關于 GET 與 POST 之間更詳細的比較可參考我的另一篇 blog??
GET 和 POST 到底有什么區(qū)別?
HTTP 響應包(服務器信息)
HTTP 的 response 包的結構如下圖??
和上面看到的請求包類似,response 響應包的第一行叫做 ”狀態(tài)行“,由 HTTP 協(xié)議版本號、狀態(tài)碼、狀態(tài)消息 三部分組成
狀態(tài)碼的作用是告訴 HTTP 客戶端(瀏覽器),HTTP 服務器是否產生了預期的 Response。
在 HTTP 1.1 協(xié)議中定義了 5 類 狀態(tài)碼,每個狀態(tài)碼由三位數字組成,首位表示類別:
- 1xx 提示信息:表示請求被成功接受,繼續(xù)處理
- 2xx 成功:表示請求已被成功接受
- 3xx 重定向:表示要完成這個請求必須進行更進一步的處理
- 4xx 客戶端錯誤:客戶端的語法錯誤或者請求無法實現
- 5xx 服務端錯誤:服務器未能實現合法的請求
常見的狀態(tài)有:200 :正常信息、302:跳轉、404 not found 等等
Tips: 持續(xù)連接 與 非持續(xù)連接(協(xié)議無狀態(tài)/keep-alive)
無狀態(tài)是指協(xié)議對于事物處理沒有記憶能力,服務器不知道客戶端是什么狀態(tài),體現在打開一個服務器的網頁和你之前打開這個服務器的網頁之間沒有任何聯(lián)系
HTTP 協(xié)議就是典型的無狀態(tài)的面向連接的協(xié)議,雖然是無狀態(tài)但是它是面向連接的協(xié)議,所以千萬不要說 HTTP 使用的是 UDP (面向無連接)的協(xié)議了?。?!
無狀態(tài)不代表不能保持TCP連接(只要不斷開連接我就不管你什么狀態(tài)不狀態(tài)的)
從 HTTP 1.1 開始,默認都開啟了 叫做 Keep-Alive 的保持連接的特性,也就是當一個網頁打開完成之后,客戶端和服務器之間用于傳輸 HTTP 數據的 TCP 連接不會關閉,如果客戶端再次訪問這個服務器上的網頁,會繼續(xù)使用這一條已經建立的 TCP 連接
當然 Keep-ALive 不會永久保持連接,它會有一個保持時間上限,你可以自行設置
如果你嘗試去檢查(F12)訪問任意一個網址
通過分析整個 URL 請求的通信過程,你會發(fā)現:
在所有的請求中不止一個 URL 請求,還會有很多其他的如靜態(tài)文件的資源請求
這其實是瀏覽器自帶的功能之一,第一次請求 url ,服務器端返回的是 HTML 頁面,然后瀏覽器會開始渲染這個頁面,但是當解析到 HTML DOM里面的圖片連接、css腳本和js腳本的連接的時候,瀏覽器就會自動地發(fā)起一個請求靜態(tài)資源的 HTTP 請求,去獲取相應的資源并渲染,最終將所有資源整合完整地展現出來
在網頁優(yōu)化中就會有一項措施,就是利用減少 HTTP 請求次數(把盡量多的css 和 js 資源合并)減少網頁請求靜態(tài)資源的次數,來提高網頁的加載速度,減輕服務器的壓力
總結
- 在這一部分,我們初步認識了 Web 的工作方式,并對一些基礎的計算機網絡相關知識有了進一步了解,特別是對于 基于 TCP 協(xié)議的 HTTP 協(xié)議,以及該協(xié)議如何在整個 客戶端-服務端 中運作。
- 當我們知道了 Web 就是一個基于 HTTP 協(xié)議的的一個服務的時候,我們就可以做好準備,去嘗試在 Go 語言中體會如何搭建一個可以運行的 Web 服務了。
關于 Golang 基礎部分 以及 計算機網絡部分讀者可以參閱我的往期 blog??
Goalng:基礎復習一遍過
漫談計算機網絡:網絡層 ------ 重點:IP協(xié)議與互聯(lián)網路由選擇協(xié)議
以上文章來源:http://www.zghlxwxcb.cn/news/detail-412371.html
看完記得留下一個??文章來源地址http://www.zghlxwxcb.cn/news/detail-412371.html
到了這里,關于Go For Web:踏入Web大門的第一步——Web 的工作方式的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!