从 URL 输入到页面渲染的全过程
前言
当用户在浏览器地址栏输入 URL 并按下回车键时,背后涉及了从物理层到应用层、从客户端到服务器端的复杂协作。本文将详细解构这一过程中的关键技术环节。
1. 协议预处理与 HSTS 机制
在发起网络请求前,现代浏览器会执行安全策略检查。
1.1 HSTS (HTTP Strict Transport Security)
为了防范中间人攻击(如 SSL Striping),浏览器会检查本地的 HSTS 列表,判断该域名是否强制要求使用 HTTPS 访问。
1.1.1 动态记录(HSTS Cache)
- 原理:当浏览器首次通过 HTTPS 成功访问站点,且服务器响应头包含
Strict-Transport-Security: max-age=...时,浏览器会将该域名记录在本地缓存中。 - 局限性:存在“首次访问安全漏洞(TOFU)”,即第一次建立连接时若被劫持,浏览器无法感知。
1.1.2 预加载列表(HSTS Preload List)
- 原理:由 Google 维护并被主流浏览器集成的硬编码列表。
- 优势:即使是首次访问,浏览器也会直接根据列表强制发起 HTTPS 连接,实现全链路安全。
1.1.3 非 HSTS 场景的处理
- 显式重定向:若请求为 HTTP,服务器返回
301/302响应,并在Location首部指明 HTTPS 地址。 - 不安全访问:若服务器未配置强制加密,浏览器会标记“Not Secure”并继续使用 HTTP。
- 连接被拒绝:若服务器仅监听 443 端口,则 80 端口的 TCP 握手将失败,返回
ERR_CONNECTION_REFUSED。
2. DNS 域名解析
将人类可读的域名转换为机器可识别的 IP 地址,遵循就近优先原则:
- 浏览器缓存:检查浏览器内存中是否存在未过期的 DNS 记录。
- 操作系统缓存:检查 OS 级 DNS 缓存及
hosts静态映射文件。 - 递归查询 (Recursive Query):操作系统向 本地 DNS 服务器 (LDNS) 发起请求。
- 迭代查询 (Iterative Query):若 LDNS 无缓存,则由其代替用户向:
- 根域名服务器获取顶级域名(TLD)服务器地址。
- TLD 域名服务器(如 .com)获取权威域名服务器地址。
- 权威域名服务器获取最终的 IP 地址记录。
3. 传输层:TCP 三次握手
在获取 IP 后,浏览器与服务器建立可靠的传输通道。
- 第一次握手:客户端发送
SYN报文,携带初始序列号seq=x。 - 第二次握手:服务器返回
SYN+ACK报文,确认号ack=x+1,并携带自己的初始序列号seq=y。 - 第三次握手:客户端发送
ACK报文,确认号ack=y+1。
核心设计目的
- 防止历史连接重启:在不可靠网络中,防止旧的重复
SYN包误建连接(见 RFC 793)。 - 同步初始序列号 (ISN):确保双方数据包的顺序性与可靠性。
- 资源分配确认:确保双方均具备发送与接收数据的能力。
4. 安全层:TLS/SSL 握手
在 TCP 连接之上,HTTPS 引入 TLS 协议进行身份核验与密钥协商。
4.1 身份认证与算法协商
- ClientHello:客户端发送支持的 TLS 版本、加密套件列表及 随机数 C。
- ServerHello:服务器选择版本、套件,发送 随机数 S 和 数字证书 (X.509)。
- 证书验签:浏览器通过内置 CA 根证书验证证书链的签名、有效期及域名匹配性。
4.2 密钥交换 (Key Exchange)
- 预主密钥 (Premaster Secret):浏览器生成一个随机数,使用证书中的公钥加密发送给服务器。
- 主密钥生成:双方结合 随机数 C + 随机数 S + 预主密钥,通过 PRF 算法各自计算出对称加密所需的主密钥 (Master Secret)。
4.3 确认安全传输
双方互发 ChangeCipherSpec 和 Finished 报文,标志后续所有应用层数据将进行对称加密。
5. HTTP 请求构造与发送
连接就绪后,浏览器封装符合协议标准的请求报文。
- 请求行:定义方法(GET/POST)、路径(URI)及版本(HTTP/1.1)。
- 请求头:
Host:指定目标服务器域名(虚拟主机支持的关键)。Cookie:携带本地存储的状态信息。Cache-Control:指示缓存策略(如max-age=0)。
- 请求体:POST 提交的数据或 JSON 负载。
6. 服务器处理与响应模型
6.1 负载均衡与网关
- 四层负载均衡 (L4):基于 IP+端口转发(如 LVS),侧重吞吐量。
- 七层负载均衡 (L7):基于 URL、Header 路由(如 Nginx, ELB),侧重业务灵活性。
- VIP (虚拟 IP):通过 Keepalived 等工具实现高可用,当主服务器故障时,VIP 漂移至备份节点。
6.2 后端逻辑处理
- 静态处理:Nginx 直接从磁盘或内存缓存中读取静态资源。
- 动态处理:API 网关转发至微服务,涉及身份认证、限流、数据库查询(Cache Aside 模式)及业务计算。
7. 浏览器渲染管线 (Rendering Pipeline)
浏览器接收到响应体(HTML 字节流)后,启动渲染引擎:
- DOM 构建:字节流 -> 字符 -> Token -> Nodes -> DOM Tree。
- CSSOM 构建:解析样式表,生成 CSSOM Tree。
- 布局树 (Layout Tree):结合 DOM 和 CSSOM,剔除
display: none等不可见节点。 - 分层 (Layering):针对 3D 转换、z-index 等生成专用的渲染层。
- 光栅化 (Rasterization):将图层转换为像素点,通常利用 GPU 加速(GPU Rasterization)。
- 合成 (Compositing):合成线程将图块(Tiles)组合并提交给显卡显示。
脚本阻塞机制
- Default:
<script>会阻塞 DOM 构建。 - async:异步下载,下载完立即执行,可能阻塞 DOM。
- defer:异步下载,待 DOM 解析完成后按顺序执行。
8. 连接释放:TCP 四次挥手
通信结束后,双向连接需有序关闭。
- FIN_WAIT_1:主动方发送
FIN。 - CLOSE_WAIT:被动方回复
ACK,此时处于半关闭状态,可继续发送剩余数据。 - LAST_ACK:被动方发送
FIN。 - TIME_WAIT:主动方回复最后一个
ACK。
为什么需要 TIME_WAIT (2MSL)?
- 可靠地终止连接:确保最后一个
ACK能到达被动方,若丢失可重传。 - 防止“已失效报文”干扰:确保旧连接产生的所有报文都在网络中消失,避免干扰后续相同四元组的新连接。
9. WebSocket 实时通信扩展
对于高频实时场景,HTTP 握手后可升级为 WebSocket。
- 握手协议:借用 HTTP 协议,Header 包含
Upgrade: websocket和Sec-WebSocket-Key。 - 状态码 101:代表协议切换成功。
- 特点:全双工通信、二进制帧结构、极低头部开销。
参考资料
- RFC 7230:HTTP/1.1 Message Syntax and Routing
- RFC 8446:The TLS Protocol 1.3
- Chromium Blog:Inside look at modern web browser
- MDN Web Docs:Critical rendering path
从 URL 输入到页面渲染的全过程
https://yicizhang00.github.io/posts/基础理论/计算机网络/URL输入浏览器发生了什么/