從輸入 URL 到頁面加載完成的過程中都發(fā)生了什么事情?
日期?:?2021年01月14日?? ? ??
正文共?:13095字


第一個問題:從輸入 URL 到瀏覽器接收的過程中發(fā)生了什么事情?
從觸屏到 CPU

CPU 內部的處理
移動設備中的 CPU 并不是一個單獨的芯片,而是和 GPU 等芯片集成在一起,被稱為 SoC(片上系統(tǒng))。


從 CPU 到操作系統(tǒng)內核
/proc/interrupts?文件來查看系統(tǒng)中所有設備的中斷請求號,以下是 Nexus 7 (2013) 的部分結果:shell@flo:/ $ cat /proc/interrupts
? ? ? ? ? ?CPU0
?17: ? ? ? ? ?0 ? ? ? GIC ?dg_timer
294: ? ?1973609 ? msmgpio ?elan-ktf3k
314: ? ? ? ?679 ? msmgpio ?KEY_POWER
/dev/input/event0?這個設備文件中,比如下面展示了一次觸摸事件所產生的信息:130|shell@flo:/ $ getevent -lt /dev/input/event0
[ ?414624.658986] EV_ABS ? ? ? ABS_MT_TRACKING_ID ? 0000835c
[ ?414624.659017] EV_ABS ? ? ? ABS_MT_TOUCH_MAJOR ? 0000000b
[ ?414624.659047] EV_ABS ? ? ? ABS_MT_PRESSURE ? ? ?0000001d
[ ?414624.659047] EV_ABS ? ? ? ABS_MT_POSITION_X ? ?000003f0
[ ?414624.659078] EV_ABS ? ? ? ABS_MT_POSITION_Y ? ?00000588
[ ?414624.659078] EV_SYN ? ? ? SYN_REPORT ? ? ? ? ? 00000000
[ ?414624.699239] EV_ABS ? ? ? ABS_MT_TRACKING_ID ? ffffffff
[ ?414624.699270] EV_SYN ? ? ? SYN_REPORT ? ? ? ? ? 00000000
從操作系統(tǒng) GUI 到瀏覽器
/dev/input/event0?文件的變化就能知道用戶進行了哪些觸摸操作,不過如果每個程序都這么做實在太麻煩了,所以在圖像操作系統(tǒng)中都會包含 GUI 框架來方便應用程序開發(fā),比如 Linux 下著名的?X。/dev/input/?目錄下的文件,然后將這些信息傳遞到 Android 的窗口管理服務(WindowManagerService)中,它會根據位置信息來查找相應的 app,然后調用其中的監(jiān)聽函數(shù)(如 onTouch 等)。擴展學習
《計算機體系結構》
《計算機體系結構:量化研究方法》
《計算機組成與設計:硬件/軟件接口》
《編碼》
《CPU自制入門》
《操作系統(tǒng)概念》
《ARMv7-AR 體系結構參考手冊》
《Linux內核設計與實現(xiàn)》
《精通Linux設備驅動程序開發(fā)》
第二個問題:瀏覽器如何向網卡發(fā)送數(shù)據?
從瀏覽器到瀏覽器內核
需要注意瀏覽器和瀏覽器內核是不同的概念,瀏覽器指的是 Chrome、Firefox,而瀏覽器內核則是 Blink、Gecko,瀏覽器內核只負責渲染,GUI 及網絡連接等跨平臺工作則是瀏覽器實現(xiàn)的
HTTP 請求的發(fā)送
DNS 查詢
dig +trace fex.baidu.com命令得到的結果(省略了一些):; <<>> DiG 9.8.3-P1 <<>> +trace fex.baidu.com
;; global options: +cmd
. ? ? ? ? ? 11157 ? IN ?NS ?g.root-servers.net.
. ? ? ? ? ? 11157 ? IN ?NS ?i.root-servers.net.
. ? ? ? ? ? 11157 ? IN ?NS ?j.root-servers.net.
. ? ? ? ? ? 11157 ? IN ?NS ?a.root-servers.net.
. ? ? ? ? ? 11157 ? IN ?NS ?l.root-servers.net.
;; Received 228 bytes from 8.8.8.8#53(8.8.8.8) in 220 ms
com. ? ? ? ? ? ?172800 ?IN ?NS ?a.gtld-servers.net.
com. ? ? ? ? ? ?172800 ?IN ?NS ?c.gtld-servers.net.
com. ? ? ? ? ? ?172800 ?IN ?NS ?m.gtld-servers.net.
com. ? ? ? ? ? ?172800 ?IN ?NS ?h.gtld-servers.net.
com. ? ? ? ? ? ?172800 ?IN ?NS ?e.gtld-servers.net.
;; Received 503 bytes from 192.36.148.17#53(192.36.148.17) in 185 ms
baidu.com. ? ? ?172800 ?IN ?NS ?dns.baidu.com.
baidu.com. ? ? ?172800 ?IN ?NS ?ns2.baidu.com.
baidu.com. ? ? ?172800 ?IN ?NS ?ns3.baidu.com.
baidu.com. ? ? ?172800 ?IN ?NS ?ns4.baidu.com.
baidu.com. ? ? ?172800 ?IN ?NS ?ns7.baidu.com.
;; Received 201 bytes from 192.48.79.30#53(192.48.79.30) in 1237 ms
fex.baidu.com. ? ? ?7200 ? ?IN ?CNAME ? fexteam.duapp.com.
fexteam.duapp.com. ?300 IN ?CNAME ? duapp.n.shifen.com.
n.shifen.com. ? ? ? 86400 ? IN ?NS ?ns1.n.shifen.com.
n.shifen.com. ? ? ? 86400 ? IN ?NS ?ns4.n.shifen.com.
n.shifen.com. ? ? ? 86400 ? IN ?NS ?ns2.n.shifen.com.
n.shifen.com. ? ? ? 86400 ? IN ?NS ?ns5.n.shifen.com.
n.shifen.com. ? ? ? 86400 ? IN ?NS ?ns3.n.shifen.com.
;; Received 258 bytes from 61.135.165.235#53(61.135.165.235) in 2 ms
這里為了方便描述,忽略了很多不同的情況,比如 127.0.0.1 其實走的是?loopback,和網卡設備沒關系;比如 Chrome 會在瀏覽器啟動的時預先查詢 10 個你有可能訪問的域名;還有 Hosts 文件、緩存時間 TTL(Time to live)的影響等。
通過 Socket 發(fā)送數(shù)據
chrome://net-internals/#spdy?頁面來發(fā)現(xiàn)。瀏覽器對同一個域名有連接數(shù)限制,大部分是 6,我以前認為將這個連接數(shù)改大后會提升性能,但實際上并不是這樣的,Chrome 團隊有做過實驗,發(fā)現(xiàn)從 6 改成 10 后性能反而下降了,造成這個現(xiàn)象的因素有很多,如建立連接的開銷、擁塞控制等問題,而像 SPDY、HTTP 2.0 協(xié)議盡管只使用一個 TCP 連接來傳輸數(shù)據,但性能反而更好,而且還能實現(xiàn)請求優(yōu)先級。
Socket 在內核中的實現(xiàn)
底層網絡協(xié)議的具體例子


0 ? ? ? ? ? ? ? ? ? 1 ? ? ? ? ? ? ? ? ? 2 ? ? ? ? ? ? ? ? ? 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ?Source Port ? ? ? ? ?| ? ? ? Destination Port ? ? ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ? ? ? ? ? ? ? ?Sequence Number ? ? ? ? ? ? ? ? ? ? ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ? ? ? ? ? ?Acknowledgment Number ? ? ? ? ? ? ? ? ? ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ?Data | ? ? ? ? ? |U|A|E|R|S|F| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
| Offset| Reserved ?|R|C|O|S|Y|I| ? ? ? ? ? ?Window ? ? ? ? ? ? |
| ? ? ? | ? ? ? ? ? |G|K|L|T|N|N| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ? Checksum ? ? ? ? ? ?| ? ? ? ? Urgent Pointer ? ? ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ? ? ? ? ? ?Options ? ? ? ? ? ? ? ? ? ?| ? ?Padding ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ? ? ? ? ? ? ? ? ? ? ? ? ? ? data ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

192.168.1.106,目標(Destination) IP 為?119.75.217.56,因此 IP 協(xié)議最重要的作用就是確定 IP 地址。192.168.1.1,但到公司就變成?172.22.22.22?了,所以在底層通信時需要使用一個固定的地址,這就是 MAC(media access control) 地址,每個網卡出廠時的 MAC 地址都是固定且唯一的。
擴展學習
《計算機網絡:自頂向下方法與Internet特色》
《計算機網絡》
《Web性能權威指南》
第三個問題:數(shù)據如何從本機網卡發(fā)送到服務器?
從內核到網絡適配器(Network Interface Card)
連接 Wi-Fi 路由
而同樣基于無線電原理的 2G/3G/LTE 也會遇到類似的問題,但它并沒有采用 Wi-Fi 那樣的獨占方案,而是通過頻分(FDMA)、時分(TDMA)和碼分(CDMA)來進行復用,具體細節(jié)這里就不展開了。
192.168.1.x?這樣的內網地址,外網無法直接向這個地址發(fā)送數(shù)據,所以網絡數(shù)據在經過路由時,路由會修改相關地址和端口,這個操作稱為?NAT?映射。運營商網絡內的路由
主干網間的傳輸
IDC 內網
這里的帶寬成本很高,是按照峰值來結算的,以每月每 Gbps(注意這里指的是 bit,而不是 Byte)為單位,北京這邊價格在十萬人民幣以上,一般網站使用 1G 到 10G 不等。

需要注意的是,一般網絡書中提到的交換機都只具備二層(MAC 協(xié)議)的功能,但在 IDC 中的交換器基本上都具備三層(IP 協(xié)議)的功能,所以不需要有專門的路由了。
服務器 CPU
擴展學習
The Datacenter as a Computer
Open Computer
《軟件定義網絡》
《大話無線通信》
第四個問題:服務器接收到數(shù)據后會進行哪些處理?
負載均衡
進行很多統(tǒng)一處理,比如防攻擊策略、防抓取、SSL、gzip、自動性能優(yōu)化等
應用層的分流策略都能在這里做,比如對 /xx 路徑的請求分到 a 服務器,對 /yy 路徑的請求分到 b 服務器,或者按照 cookie 進行小流量測試等
緩存,并在后端服務掛掉的時候顯示友好的 404 頁面
監(jiān)控后端服務是否異常
??
Web Server 中的處理
進入后端語言
Web 框架(Framework)
讀取數(shù)據
擴展學習
《深入理解Nginx》
《Python源碼剖析》
《深入理解Java虛擬機》
《數(shù)據庫系統(tǒng)實現(xiàn)》
第五個問題:服務器返回數(shù)據后瀏覽器如何處理?
從 01 到字符
用戶設置,在瀏覽器中可以指定頁面編碼
HTTP 協(xié)議中
?中的 charset 屬性值對于 JS 和 CSS
對于 iframe
外鏈資源的加載
JavaScript 的執(zhí)行
從字符到圖片
跨平臺 2D 繪制庫
GPU 合成
擴展學習
Chromium
Mozilla Hacks
Surfin’ Safari
第六個問題:瀏覽器如何將頁面展現(xiàn)出來?
Framebuffer
/dev/fb0?文件中,這個文件實際上一個內存區(qū)域的映射,這段內存區(qū)域稱為 Framebuffer。從內存到 LCD

LCD 顯示

另外直接使用三種顏色的 LED 也是可行的,它能避免了濾光導致的光子浪費,降低耗電,很適用于智能手表這樣的小屏幕,Apple 收購的 LuxVue 公司就采用的是這種方式,感興趣的話可以去研究它的專利

并不是所有顯示器的亮度都能達到 256,在選擇顯示器時有個參數(shù)是 8-Bit 或 6-Bit 面板,其中 8-Bit 的面板能在物理上達到 256 種亮度,而 6-Bit 的則只有 64 種,它需要靠刷新率控制(Frame rate control)技術來達到 256 的效果。
擴展學習
《Computer Graphics, 3rd Edition : Principles and Practices》
《交互式計算機圖形學》
本文所忽略的內容
內存相關
堆,這里的分配策略有很多,比如 malloc?的實現(xiàn)
棧,函數(shù)調用,已經有很多優(yōu)秀的文章或書籍介紹了
內存映射,動態(tài)庫加載等
隊列幾乎無處不在,但這些細節(jié)和原理沒太大關系
各種緩存
CPU 的緩存、操作系統(tǒng)的緩存、HTTP 緩存、后端緩存等等
各種監(jiān)控
很多日志會保存下來以便后續(xù)分析
FAQ
大家的討論
最后
—?THE END —

