一個(gè)經(jīng)典的面試題:你輸入網(wǎng)址后到頁面顯示出來棋嘲,中間發(fā)生了什么店溢?
物理
先扯個(gè)淡叁熔。輸入網(wǎng)址的時(shí)候當(dāng)然首先動(dòng)作的是鍵盤。如果是外接USB鍵盤床牧,則是鍵盤讀取按鍵信號(hào)荣回,然后傳遞給操作系統(tǒng)。如果是觸摸屏戈咳,則有操作系統(tǒng)負(fù)責(zé)識(shí)別觸摸區(qū)域心软,得到按鍵信息壕吹。
操作系統(tǒng)
用戶端常見的操作系統(tǒng)包括:微軟的Windows、蘋果的macOS删铃、開源的Linux耳贬、Google的Android、蘋果的iOS等猎唁。
操作系統(tǒng)負(fù)責(zé)管理所有硬件效拭,提供程序執(zhí)行環(huán)境,為上層程序提供基本的輸入輸出等功能胖秒。除了這些基本功能外(一般叫做操作系統(tǒng)內(nèi)核)缎患,系統(tǒng)還會(huì)提供一些基礎(chǔ)設(shè)施。比如網(wǎng)絡(luò)Socket API阎肝,圖形圖像功能等挤渔。這些功能都是瀏覽器所需要的。
瀏覽器作為一個(gè)程序风题,從操作系統(tǒng)處得到用戶輸入的網(wǎng)址和輸入完成的命令判导。后續(xù)的所有功能都需要調(diào)用操作系統(tǒng)對(duì)應(yīng)的API來實(shí)現(xiàn)。
瀏覽器
常見的瀏覽器軟件包括:
- Google的Chrome沛硅。Webkit內(nèi)核(新版轉(zhuǎn)向Blink)和V8 JS引擎
- 微軟的IE眼刃。Trident內(nèi)核,IE 11之后不再更新摇肌。
- 微軟的Edge擂红。EdgeHTML內(nèi)核,Chakra JS引擎围小。
- Mozilla的Firefox昵骤。Gecko內(nèi)核和SpiderMonkey JS引擎。
- 蘋果的Safari肯适。Webkit內(nèi)核变秦,Nitro JS引擎。
- Opera框舔。原Presto蹦玫,新版也轉(zhuǎn)向Blink和V8。
瀏覽器接收到網(wǎng)址后刘绣,開始以下的流程樱溉。
DNS
首先瀏覽器需要聯(lián)系網(wǎng)站服務(wù)器。網(wǎng)址额港,即URL饺窿,被解析為若干部分。例如對(duì)于www.baidu.com
移斩,實(shí)際上它的完整形式是:http://www.baidu.com:80/
肚医。其中包括了以下部分:
- 協(xié)議:http
- 域名:www.baidu.com绢馍。其中
baidu.com
是百度的域名,www是這個(gè)域名下的二級(jí)域名肠套。 - 端口:80
- 路徑:/
其中協(xié)議部分默認(rèn)為http舰涌,端口對(duì)于http來說默認(rèn)是80,對(duì)于https來說是443你稚。接下來如果域名部分不是IP的話瓷耙,需要DNS協(xié)議得到服務(wù)器的IP地址。
DNS本身是一個(gè)基于UDP協(xié)議的網(wǎng)絡(luò)協(xié)議刁赖。專門用于服務(wù)器和IP地址的查詢搁痛。DNS服務(wù)由DNS服務(wù)器提供,默認(rèn)端口是UDP的53宇弛。一個(gè)計(jì)算機(jī)的DNS服務(wù)器配置在操作系統(tǒng)中鸡典,是上網(wǎng)配置的基本元素之一(另外幾個(gè)包括IP地址,子網(wǎng)掩碼枪芒,默認(rèn)網(wǎng)關(guān))彻况。
瀏覽器把域名發(fā)送給系統(tǒng)默認(rèn)DNS服務(wù)器。如果該服務(wù)器本地有緩存舅踪,且緩存未過期纽甘,則直接返回結(jié)果。否則向上一級(jí)DNS服務(wù)器查詢抽碌,直到DNS根服務(wù)器悍赢。DNS協(xié)議最終會(huì)返回A記錄(IPv4)或者AAAA記錄(IPv6)或者Alias(別名)等。如果DNS失敗咬展,瀏覽器會(huì)提示域名找不到或者DNS錯(cuò)誤泽裳。
到此為止瞒斩,瀏覽器知道了網(wǎng)址的對(duì)應(yīng)服務(wù)器IP地址和端口破婆,然后就通過TCP協(xié)議發(fā)起網(wǎng)絡(luò)請(qǐng)求。但是發(fā)起的是什么請(qǐng)求取決于網(wǎng)址的協(xié)議是HTTP還是HTTPS胸囱。
HTTP
HTTP是基于文本的協(xié)議祷舀,客戶端和服務(wù)器一問一答,有固定格式烹笔。包括HTTP Header和Boby裳扯。頭部使用換行符進(jìn)行分隔字段,一行一個(gè)字段谤职。字段中使用冒號(hào):
分隔Key和Value饰豺。例如:
GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.14 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
DNT: 1
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: BAIDUID=F27F5856EB13162499CC2DB7DC4FD050:FG=1;
最重要是開始的幾行:
- GET / HTTP/1.1:使用GET動(dòng)作(另外還有POST,PUT等)允蜈,獲得
/
路徑的內(nèi)容(還記得網(wǎng)址里最后的/
么)冤吨,采用HTTP/1.1
協(xié)議 - Host: www.baidu.com:主機(jī)頭為www.baidu.com蒿柳。
- Connection: keep-alive:結(jié)束后保持網(wǎng)絡(luò)連接,以節(jié)省TCP建立的開銷漩蟆。
- User-Agent:報(bào)告瀏覽器參數(shù)垒探。
- Accept:瀏覽器能接受的應(yīng)答格式。
這是百度服務(wù)器返回的Response Header怠李。
HTTP/1.1 200 OK
Server: bfe/1.0.8.18
Date: Mon, 13 Mar 2017 12:23:41 GMT
Content-Type: text/html;charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: private
Expires: Mon, 13 Mar 2017 12:23:41 GMT
Content-Encoding: gzip
應(yīng)答的主要字段:
- HTTP/1.1 200 OK:
HTTP/1.1
協(xié)議圾叼,返回代碼200,含義為請(qǐng)求成功完成 - Server:百度服務(wù)器信息
- Date:時(shí)間
- Content-Type:應(yīng)答的格式和編碼捺癞。這是和瀏覽器請(qǐng)求對(duì)應(yīng)的夷蚊。
- Expires: 過期時(shí)間,在這個(gè)時(shí)間之前的話應(yīng)答不會(huì)過期髓介,允許瀏覽器進(jìn)行本地緩存撬码。
HTTPS
HTTPS協(xié)議是在HTTP協(xié)議之下的加密層“姹#客戶端和服務(wù)器建立起一個(gè)加密通道后進(jìn)行數(shù)據(jù)傳輸呜笑。傳輸?shù)臄?shù)據(jù)仍然是HTTP文本。一旦部署了HTTPS彻犁,那么數(shù)據(jù)就不再是明碼叫胁,可以防止數(shù)據(jù)在傳輸過程中的泄露。另外汞幢,SSL證書頒發(fā)機(jī)構(gòu)在頒發(fā)EV證書的時(shí)候驼鹅,會(huì)嚴(yán)格驗(yàn)證機(jī)構(gòu)身份,可以在一定程度上避免釣魚網(wǎng)站森篷。
SSL證書分為DV输钩,OV和EV三種。DV僅驗(yàn)證域名所有者仲智,EV會(huì)驗(yàn)證機(jī)構(gòu)身份买乃。因此數(shù)據(jù)安全要求較高的網(wǎng)站,例如金融機(jī)構(gòu)钓辆,一般都申請(qǐng)EV證書剪验。訪問的時(shí)候?yàn)g覽器地址欄會(huì)出現(xiàn)綠色機(jī)構(gòu)名稱。
部署正確的HTTPS Web服務(wù)器中有一個(gè)經(jīng)過權(quán)威認(rèn)證的數(shù)字證書前联。數(shù)字證書包含有服務(wù)器公鑰和簽名算法功戚。瀏覽器和服務(wù)器通過非對(duì)稱加密算法公私鑰機(jī)制進(jìn)行通信,協(xié)商出一個(gè)雙方都支持的對(duì)稱加密算法和加密的秘鑰似嗤。
數(shù)字證書由一個(gè)叫做CA(Certification Authority)的機(jī)構(gòu)頒發(fā)啸臀,包含由服務(wù)器公鑰,訂閱人相關(guān)信息(名稱烁落,域名等)乘粒,最后由頒發(fā)者使用自己的證書進(jìn)行簽名席揽。CA的機(jī)構(gòu)證書由另一個(gè)CA簽名,直至最后一種特殊的證書為止:自己給自己簽名谓厘。這種證書叫做根證書幌羞,預(yù)先內(nèi)置在操作系統(tǒng)或者瀏覽器中。由此數(shù)字證書形成一個(gè)證書鏈竟稳。
其中baidu.com
證書負(fù)責(zé)百度域名下的HTTPS運(yùn)作属桦,此證書由一張GlobalSign Organization Validation CA
的中間證書簽名,而這張中間證書由GlobalSign Root CA
即根證書頒發(fā)他爸。
不由根證書直接簽發(fā)是因?yàn)榘踩蚰舯觥R驗(yàn)楦C書一般都內(nèi)置于系統(tǒng),更新這個(gè)列表是很慢的诊笤。而系統(tǒng)只驗(yàn)證CA是否可信任系谐,只要受信任,它可以簽發(fā)任何域名的證書讨跟。因此根證書私鑰一旦泄露或發(fā)生其他問題造成證書不安全纪他,后果就很嚴(yán)重。結(jié)果是根證書私鑰一般存放在和銀行金庫一樣安全的地方晾匠,不可能經(jīng)常拿出來為客戶簽名茶袒。一般由根證書簽發(fā)一些中間證書,平時(shí)由中間證書來簽發(fā)終端證書凉馆,一旦出問題薪寓,可以直接吊銷這張中間證書。
SSL證書的作用是構(gòu)建一個(gè)可信任的加密數(shù)據(jù)通道澜共,在網(wǎng)絡(luò)中不止可在HTTP中使用向叉。比如和FTP搭配使用就是FTPS。
網(wǎng)絡(luò)接入
其實(shí)DNS也是需要通過網(wǎng)絡(luò)的嗦董。但是網(wǎng)絡(luò)放到現(xiàn)在來說吧母谎。
接下來,數(shù)據(jù)需要通過網(wǎng)絡(luò)發(fā)送出去展懈。網(wǎng)絡(luò)分為電信销睁、移動(dòng)、聯(lián)通寬帶和手機(jī)網(wǎng)絡(luò)存崖。以下是網(wǎng)絡(luò)層的模型:
不同的接入方式在物理層和網(wǎng)絡(luò)鏈路層是不同的,但是到了IP層就都統(tǒng)一了睡毒。
- 有線寬帶
電腦通過水晶頭(RJ45)連接網(wǎng)線(雙絞線)来惧,后連接到網(wǎng)絡(luò)設(shè)備上(HUB、路由器演顾、交換機(jī)等)供搀。這是以太網(wǎng)的接入方式隅居。
- 無線寬帶
設(shè)備通過天線與接入點(diǎn)(Access Point,AP)通信葛虐,然后AP接入網(wǎng)絡(luò)胎源。AP后端一般通過以太網(wǎng)有線方式接入網(wǎng)絡(luò)。即無線僅作為設(shè)備和網(wǎng)絡(luò)末端的鏈接方式屿脐。
通信協(xié)議的事實(shí)標(biāo)準(zhǔn)是802.11家族涕蚤,例如802.11g,802.11n的诵,802.11ac等万栅。
- 手機(jī)
設(shè)備通過天線與基站通信,然后基站接入網(wǎng)絡(luò)西疤。這是最復(fù)雜的一種方式烦粒,電信運(yùn)營商的天線、基站代赁、協(xié)議等的標(biāo)準(zhǔn)浩如煙海扰她。目前還在運(yùn)營的接入標(biāo)準(zhǔn)包括:GSM,CDMA芭碍,WCDMA义黎,TDSCDMA,CDMA2000豁跑,TD-LTE廉涕,F(xiàn)DD-LTE等。
運(yùn)營商
網(wǎng)絡(luò)通過末端進(jìn)入運(yùn)營商網(wǎng)絡(luò)之后艇拍,需要通過一整套設(shè)備和規(guī)則進(jìn)行數(shù)據(jù)傳遞狐蜕。主要網(wǎng)絡(luò)設(shè)備就是路由器和交換機(jī)。
多臺(tái)設(shè)備通過交換機(jī)組成一個(gè)子網(wǎng)卸夕。子網(wǎng)之間通過路由器連接层释。路由器在內(nèi)部維護(hù)了一張路由表,當(dāng)有數(shù)據(jù)包到達(dá)時(shí)快集,查詢路由表贡羔,決定數(shù)據(jù)包通過哪一個(gè)網(wǎng)卡,傳輸?shù)较乱粋€(gè)子網(wǎng)去个初。無數(shù)個(gè)路由器相互連接乖寒,把數(shù)據(jù)包傳輸?shù)阶罱K節(jié)點(diǎn)。這部分內(nèi)容資料最多是Cisco認(rèn)證相關(guān)教材和產(chǎn)品說明院溺。
- 海底光纜
這是屬于物理層的內(nèi)容楣嘁,屬于運(yùn)營商重要的組成部分。網(wǎng)絡(luò)信號(hào)最終需要線纜通信,目前主流的大帶寬通信手段就是光纖和光纜逐虚。而跨洲的通信就是通過海底光纜聋溜。若干年前,臺(tái)灣地震叭爱,海底光纜故障撮躁,中斷了大量的海外網(wǎng)絡(luò)訪問。圖為中國海底光纜分布:
機(jī)房
最終數(shù)據(jù)到達(dá)網(wǎng)站所在機(jī)房买雾。
網(wǎng)站在機(jī)房一般會(huì)有多臺(tái)服務(wù)器把曼,通過交換機(jī)互相連接后通過路由器作為網(wǎng)關(guān)接入運(yùn)營商。數(shù)據(jù)到達(dá)網(wǎng)關(guān)后會(huì)被進(jìn)行過濾和處理凝果,通過防火墻祝迂、入侵檢測(cè)等網(wǎng)絡(luò)安全方面的設(shè)備,然后通過負(fù)載均衡等設(shè)備器净,最終達(dá)到目標(biāo)服務(wù)器型雳。
服務(wù)器操作系統(tǒng)
與用戶端一樣,服務(wù)器也需要通過操作系統(tǒng)運(yùn)行網(wǎng)站相關(guān)軟件山害。不同的是服務(wù)器的操作系統(tǒng)是為長時(shí)間穩(wěn)定高效運(yùn)行特別優(yōu)化過的纠俭。常見的服務(wù)器操作系統(tǒng)包括:Linux,Unix家族(FreeBSD浪慌,Solaris等)冤荆,Windows Server(2003,2008,2012,2016)。
Web服務(wù)器軟件
終于到達(dá)處理HTTP協(xié)議的軟件了权纤。這類軟件叫做Web Server钓简。主流的包括Windows系統(tǒng)上的IIS,開源的Apache汹想,Nginx等外邓。
- HTTP協(xié)議處理
Web Server最重要的角色就是處理HTTP協(xié)議,給瀏覽器規(guī)范的應(yīng)答古掏。處理網(wǎng)絡(luò)請(qǐng)求和相關(guān)連接损话。因此吞吐量和性能是一個(gè)重要的指標(biāo)。開源軟件中Nginx是高性能Web服務(wù)器的主流選擇槽唾,IIS是Windows上的標(biāo)準(zhǔn)軟件丧枪。
- HTTPS協(xié)議處理
HTTPS協(xié)議相關(guān)的證書、加解密庞萍、簽名等也需要Web服務(wù)器處理拧烦。但是開源軟件中,一般選擇調(diào)用OpenSSL
處理挂绰,而IIS是微軟自行實(shí)現(xiàn)的加密庫屎篱。
- 靜態(tài)文件
Web Server能夠直接處理的只有靜態(tài)文件服赎。比如請(qǐng)求http://upload.jianshu.io/admin_banners/web_images/2870/48782c3773b1132ee6c594e56211f64499669099.jpg
葵蒂,那么Web服務(wù)器根據(jù)網(wǎng)址在服務(wù)器磁盤上找到這個(gè)路徑的文件交播,返回文件內(nèi)容。
- 動(dòng)態(tài)內(nèi)容接口
但是現(xiàn)在的網(wǎng)站除了css践付、js和圖片等資源外秦士,大量的內(nèi)容都是動(dòng)態(tài)內(nèi)容。Web服務(wù)器需要一個(gè)標(biāo)準(zhǔn)接口與不同語言的代碼配合永高,來動(dòng)態(tài)生成網(wǎng)頁內(nèi)容隧土。這個(gè)接口包括CGI、FastCGI命爬、ISAPI等曹傀。其中ISAPI屬于IIS,開源服務(wù)器一般支持CGI和FastCGI等饲宛。
CDN和代理
在進(jìn)入動(dòng)態(tài)內(nèi)容之前皆愉,插入一段靜態(tài)資源處理的現(xiàn)狀。
一般來說艇抠,靜態(tài)資源很少變化幕庐,而請(qǐng)求量很大。而通過前文可以知道用戶和服務(wù)器之間有眾多的網(wǎng)絡(luò)設(shè)備和線路需要通過家淤。為了加速靜態(tài)資源(尤其是圖片)的訪問异剥,服務(wù)器離用戶越近越好。因此產(chǎn)生了CDN這個(gè)需求絮重。
CDN即內(nèi)容分發(fā)網(wǎng)絡(luò)冤寿,通過在各地部署服務(wù)器,在服務(wù)器之間同步靜態(tài)資源青伤,然后就近提供給用戶督怜。從域名上就能看出簡(jiǎn)書用了CDN。比如Logo的網(wǎng)址:http://cdn-qn0.jianshu.io/assets/web/logo-58fd04f6f0de908401aa561cda6a0688.png
應(yīng)用服務(wù)器
請(qǐng)求到達(dá)應(yīng)用服務(wù)器之后潮模,就開始網(wǎng)站自己的活了亮蛔。應(yīng)用服務(wù)器通過CGI、FastCGI擎厢、ISAPI等接口與Web服務(wù)器通信究流,獲得HTTP請(qǐng)求,返回HTTP應(yīng)答动遭。主流應(yīng)用服務(wù)器根據(jù)語言和平臺(tái)分:
- Windows和.NET:IIS芬探。IIS放在這里是因?yàn)锳SP.NET深度集成,無法分出厘惦。
- Java:Jetty偷仿,JBoss哩簿,Tomcat,WebLogic等
- PHP:php-cgi
應(yīng)用服務(wù)器可以作為dll運(yùn)行在Web服務(wù)器中(比如IIS酝静,但是IIS也支持FastCGI)节榜,或者作為獨(dú)立進(jìn)程肥照,通過IPC與Web服務(wù)器通信耕陷。
接下來就是程序內(nèi)部的事情了桩匪。省略坑律。
數(shù)據(jù)庫服務(wù)器
應(yīng)用服務(wù)器在生成網(wǎng)站內(nèi)容的過程中一般需要連接數(shù)據(jù)庫存取數(shù)據(jù)硫嘶。目前主流數(shù)據(jù)庫包括:
- MySQL:開源軟件锰悼,SUN公司被收購后由Oracle負(fù)責(zé)
- MariaDB:SUN被收購后勒极,因?yàn)樯鐓^(qū)與Oracle的糾紛饲帅,從MySQL分支出來的版本敞恋。
- SQL Server:微軟開發(fā)的商用數(shù)據(jù)庫丽啡。其中Express Edtion免費(fèi)。
- Oracle:Oracle公司開發(fā)的商用數(shù)據(jù)庫硬猫。
- PostgreSQL:開源軟件补箍,號(hào)稱開源中功能最強(qiáng)。
- DB2:IBM公司開發(fā)的商用數(shù)據(jù)庫浦徊。
- Redis: NoSQL馏予,支持多種數(shù)據(jù)結(jié)構(gòu)
- MongoDB: NoSQL
HTML和CSS解析
最終應(yīng)用服務(wù)器生成了HTML,然后給Web Server盔性。Web Server生成HTTP應(yīng)答霞丧,然后通過復(fù)雜的網(wǎng)絡(luò)線路回到用戶電腦中。用戶電腦的操作系統(tǒng)把應(yīng)答給瀏覽器冕香。瀏覽器開始渲染蛹尝。
以下是瀏覽器渲染的主要過程:
開始從頭到尾解析HTML,并生成DOM樹悉尾。其中如果有外鏈資源突那,需要再次通過網(wǎng)絡(luò)層以此下載。如果是<script>
標(biāo)簽构眯,則需要調(diào)用JS引擎執(zhí)行腳本愕难。如果是css,則開始解析CSS惫霸,得到一系列樣式規(guī)則猫缭。DOM樹生成之后,與樣式規(guī)則拼接壹店,得到渲染樹猜丹。
渲染樹經(jīng)過排版引擎得到最終的渲染位置和樣式,然后調(diào)用操作系統(tǒng)的繪圖API繪制頁面(部分內(nèi)容會(huì)調(diào)用顯卡進(jìn)行硬件加速)硅卢。
JavaScript引擎
現(xiàn)代瀏覽器中JS部分越來越重要射窒,因?yàn)榍岸酥蠮S的比例越來越大藏杖。其中Google Chrome內(nèi)置的V8引擎已經(jīng)超越瀏覽器,在node.js
脉顿、桌面開發(fā)等其他領(lǐng)域也應(yīng)用廣泛蝌麸。比如我現(xiàn)在寫這篇文章用的Visual Studio Code
就內(nèi)置V8引擎。
JS引擎負(fù)責(zé)解釋并執(zhí)行JS語言(現(xiàn)代瀏覽器一般內(nèi)置JIT編譯器以加速執(zhí)行)弊予,并通過瀏覽器或者其他環(huán)境提供API給JS使用祥楣。瀏覽器中最重要的API就是DOM(Document Object Model)和BOM(Browser Object Model)开财。JS正是通過這些接口來操作HTML汉柒,并在此基礎(chǔ)上獲得動(dòng)態(tài)頁面的效果。