阿里面试官问“从 URL 输入到返回请求的过程“,难点在哪?
一、为什么这道题能拉开差距
先给结论: 这道题本身没有标准答案,但它能像一面镜子一样,照出候选人知识体系的深度、广度和结构化表达能力。
1.1 初级回答长什么样
大多数候选人的回答基本是这个模板:
用户在浏览器输入 URL,浏览器先解析域名,通过 DNS 找到服务器 IP,然后建立 TCP 连接,发送 HTTP 请求,服务器处理请求并返回 HTML,浏览器渲染页面。
这段话没有错,但每一句话都只是「名词的堆砌」。面试官如果在这里追问一句「DNS 查询具体是怎么查的」「TCP 为什么是三次握手而不是两次」,很多人就卡住了。
1.2 面试官真正想考察什么
阿里的面试官问这道题,本质上是在做一次知识体系的压力测试。他想知道的不是你会不会背流程,而是你对以下四个维度的理解:
-
广度:你是否知道这条链路上涉及到的所有关键组件,包括浏览器、操作系统、DNS、TCP/IP、TLS、HTTP、负载均衡、网关、后端服务、数据库、CDN、渲染引擎等。
-
深度:当面试官随便挑一个环节追问时,你能不能继续往下挖三层。比如问「三次握手」,你能不能讲清序列号机制、SYN 队列、SYN Flood 攻击和 TCP Fast Open。
-
结构化:你能不能把一条很长的链路拆成清晰的阶段,每一阶段先讲目的、再讲过程、最后讲异常情况,让面试官觉得你「想得清楚」。
-
工程视角:你能不能从「理论」跳到「生产实践」。比如 DNS 解析不只是查一个 IP,还涉及缓存策略、CDN 调度、劫持防护;TCP 不只是握手,还涉及超时重传、拥塞控制;HTTP 不只是请求响应,还涉及连接复用、头部压缩。
所以,这篇文章会沿着「一条完整链路 + 每个环节的工程细节 + 高频追问」来展开。全文会非常长,建议收藏后分阶段阅读。我们把整条链路拆成十个阶段一一击破。
二、从敲下回车开始:浏览器在做什么
很多人以为「输入 URL 到返回请求」是从网络请求开始的,但其实在数据包离开你的电脑之前,浏览器内部已经完成了一系列复杂的处理。理解这一步,才能回答出区别于普通候选人的「第一层差异」。
2.1 你真的输入的是一个 URL 吗
用户在地址栏敲下的东西,不一定是一个合法的 URL。浏览器需要先判断输入内容的类型:
-
如果输入的是纯域名,比如
baidu.com,浏览器会自动补全协议,默认使用https://,并加上路径/。 -
如果输入的是关键词,比如「淘宝」,浏览器会把它交给搜索引擎,而不是当成 URL 访问。
-
如果输入包含明显的协议头,比如
http://或https://,则直接按 URL 处理。
这个「输入分类」的过程由浏览器的地址栏(Omnibox)完成,它还会根据历史记录、书签、搜索引擎建议提供联想候选。所以严格来说,面试中说的「输入 URL」,其实暗含了「浏览器已经识别出这是一个合法的 URL」这个前提。
2.2 URL 的完整结构
一个完整的 URL 由以下部分组成:
text
scheme://user:password@host:port/path?query#fragment
以 https://www.example.com:443/path/to/resource?key=value&name=test#section 为例:
| 组成部分 | 示例值 | 作用 |
|---|---|---|
| scheme | https | 协议,决定使用什么方式通信 |
| user:password | (本例为空) | 可选的用户认证信息,现已不推荐使用 |
| host | www.example.com | 主机名,需要解析成 IP |
| port | 443 | 端口,省略时使用协议默认端口 |
| path | /path/to/resource | 服务器上的资源路径 |
| query | key=value&name=test | 查询参数,以键值对形式传递 |
| fragment | section | 片段标识,用于定位页面内部锚点 |
需要特别说明的是,fragment 在 HTTP 请求中不会被发送到服务器,它只在客户端用于定位页面位置。这一点面试中经常被问到,很多人会误以为 fragment 也会随着请求发出。
2.3 浏览器对 URL 的规范化与编码
URL 默认只允许 ASCII 字符。当你输入包含中文或其他非 ASCII 字符的 URL 时,浏览器会进行编码处理:
-
域名部分使用 Punycode 编码。例如「淘宝.com」会被转换成
xn--czr0bb03b.com这样的形式,再交给 DNS 解析。 -
路径和查询参数部分使用 百分号编码(Percent-Encoding)。例如中文「你好」会被编码成
%E4%BD%A0%E5%A5%BD,空格被编码成%20或+。
这一步的价值在于:它回答了「中文域名到底是怎么被访问的」这类冷门但能体现知识深度的问题。
2.4 强制 HTTPS 与 HSTS
如果你输入的是 http://example.com,但该站点配置了 HSTS(HTTP Strict Transport Security),浏览器会在本地直接改写为 https://,根本不发 HTTP 请求。HSTS 通过响应头 Strict-Transport-Security 生效,例如:
text
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
它解决的核心问题是:避免每一次都先走不安全的 HTTP 再被 301 跳转到 HTTPS,从而减少中间人攻击的窗口期。这道追问能体现你对「安全细节」的敏感度。
2.5 浏览器多进程架构下的导航流程
现代浏览器(以 Chrome 为例)采用多进程架构。一次地址栏导航会涉及以下几个进程的协作:
-
浏览器主进程:负责地址栏输入、UI 展示、进程调度,发起导航请求。
-
渲染进程:负责页面的解析和渲染。导航发生时,可能会新开一个渲染进程,也可能复用旧的。
-
网络进程:负责实际的网络请求,包括 DNS 解析、TCP 连接、TLS 握手、HTTP 请求等,是这条链路中的「执行者」。
-
GPU 进程:负责页面的绘制和合成。
完整的进程协作大致是:浏览器主进程把导航请求交给网络进程,网络进程负责完成整条网络链路,拿到响应后再把数据通过 IPC 交给渲染进程渲染。如果你能在回答中明确提出「网络进程」这个概念,就比只说「浏览器发请求」的候选人高出一个层次。
2.6 导航开始前的钩子:beforeunload
如果当前页面还有未提交的表单内容或正在播放的视频,浏览器会在离开当前页面前触发 beforeunload 事件,询问用户是否确认离开。这个事件可以阻止导航继续进行。
这是一个小但实用的细节:它说明「网络请求」不是从用户敲回车的那一刻就必然发起的,浏览器有一个「允许离开」的确认阶段。
2.7 预解析与预连接
为了加速导航,浏览器还有一个「预热」机制。当用户还在输入或者鼠标悬停在链接上时,浏览器就可能预测用户接下来要访问哪个域名,提前做 DNS 预解析(DNS Prefetch) 或 TCP 预连接(Preconnect):
html
<link rel="dns-prefetch" href="//example.com"> <link rel="preconnect" href="//api.example.com">
这样当真正需要请求时,DNS 和 TCP 可能已经提前就绪。这个知识点属于「性能优化与浏览器机制」的交集,在回答中作为延伸出来讲会很加分。
三、DNS 解析:一个域名是如何变成 IP 的
如果面试官只能追问一个环节,他大概率会选择 DNS。因为 DNS 是整条链路中最「看不见摸不着」但又最「卡时间」的部分,也是大多数候选人只懂皮毛的部分。
3.1 为什么需要 DNS
网络层最终是靠 IP 地址通信的,但 IP 地址对人不友好。DNS(Domain Name System)的核心作用就是提供「域名到 IP」的映射,让我们可以用有意义的域名访问服务,而不必记住一串数字。
但 DNS 的意义远不止「查个 IP」。站在工程视角,它还承担了:
-
负载均衡:同一个域名可以返回不同 IP,实现流量分发。
-
CDN 调度:根据用户地理位置返回最近的节点 IP。
-
故障转移:某个机房挂了,可以摘掉对应 IP,把流量切到其他机房。
-
服务发现:在微服务体系中,服务名到实例地址的映射也依赖类似 DNS 的机制。
理解这一点,你就能明白为什么大厂对 DNS 环节极其重视。
3.2 DNS 查询的完整链路
浏览器拿到域名后,并不会直接去问「根域名服务器」,而是先走一层层缓存。DNS 查询的完整顺序如下:
-
浏览器 DNS 缓存:浏览器自身会缓存最近查询过的域名,通常缓存时间很短(Chrome 大约 1 分钟)。
-
操作系统缓存:如果浏览器缓存未命中,会查询操作系统缓存。在 Windows 上是 DNS Client 服务,在 Linux 上通常没有系统级缓存,而是由
/etc/resolv.conf指定的解析器直接查询。 -
hosts 文件:操作系统在查询 DNS 之前,会先检查本机 hosts 文件是否有该域名的映射。这也是本地开发和域名劫持的常用手段。
-
路由器缓存:家庭或公司网络的路由器一般也有自己的 DNS 缓存。
-
本地 DNS 服务器(LDNS):通常由 ISP(互联网服务提供商)提供,如电信、联通、移动的 DNS 服务器。如果以上缓存都未命中,请求会发给 LDNS。
如果 LDNS 也没有缓存,它就会代替客户端进行递归查询,从根域名服务器开始一级一级查下去。
3.3 递归查询与迭代查询
这是 DNS 面试题的核心概念,一定要分清楚:
-
递归查询:客户端把查询任务完全交给 LDNS,LDNS 负责查到底,最后只把结果返回给客户端。客户端和 LDNS 之间是递归关系。
-
迭代查询:LDNS 逐级向上查询时,根域名服务器、顶级域名服务器、权威域名服务器都不替它查到底,而是告诉它「下一步去哪里问」。LDNS 和上级服务器之间是迭代关系。
一个完整的过程是这样的:
text
客户端 --递归查询--> 本地DNS服务器 本地DNS服务器 --迭代查询--> 根域名服务器 根域名服务器:"我不知道 www.example.com 的 IP,但我知道 com 的权威服务器在哪" 本地DNS服务器 --迭代查询--> .com 顶级域名服务器 .com 顶级域名服务器:"我不知道 www 的 IP,但我知道 example.com 的权威服务器在哪" 本地DNS服务器 --迭代查询--> example.com 权威域名服务器 权威域名服务器:"www.example.com 的 IP 是 93.184.216.34"
面试官如果问「递归和迭代有什么区别」,核心区别就是:递归是别人替你查到底,迭代是别人只给你指路,你自己接着问。
3.4 DNS 的分层结构
域名系统是一个树形层级结构,从右到左层级依次升高:
text
根域(.,隐含不写)
└── 顶级域(com、cn、org、net...)
└── 二级域(example.com、baidu.com...)
└── 子域(www.example.com、api.example.com...)
需要记住的是:全球有 13 组根域名服务器(从 a.root-servers.net 到 m.root-servers.net),这 13 组不是 13 台物理机器,而是 13 个 IP 集群,通过 Anycast 技术分布在全球各地。顶级域名服务器负责 com、cn、org 等顶级域,权威域名服务器负责具体某个域名(如 example.com)的记录。
3.5 DNS 报文与常见记录类型
DNS 查询和响应使用同一个报文格式,主要字段包括:
-
Transaction ID:事务 ID,用于匹配请求和响应。
-
Flags:标志位,标记是查询还是响应、是否有错误等。
-
Questions:查询的域名、类型和类别。
-
Answers:应答记录,即查询结果。
常见的 DNS 记录类型:
| 记录类型 | 作用 | 示例 |
|---|---|---|
| A | 将域名指向 IPv4 地址 | example.com → 93.184.216.34 |
| AAAA | 将域名指向 IPv6 地址 | example.com → 2606:2800:220:1:248:1893:25c8:1946 |
| CNAME | 域名别名,指向另一个域名 | www.example.com → example.com |
| NS | 指定该域名的权威 DNS 服务器 | example.com 的 NS 记录 |
| MX | 邮件交换记录 | 用于邮件投递 |
| TXT | 文本记录,常用于域名验证、SPF | DNS 验证记录 |
面试中常问的一个点是:CNAME 和 A 记录的区别。A 记录直接把域名解析到 IP,CNAME 则是把域名指向另一个域名,最终还是要通过别名域名的 A 记录才能拿到 IP。所以 CNAME 会导致额外的一次查询。
3.6 一个容易被忽略的点:CNAME 对 CDN 的意义
CDN(内容分发网络)的核心是让用户访问离他最近的节点。实现方式通常是:
-
让你的主域名(如 www.example.com)CNAME 到 CDN 厂商提供的域名(如 example.cdn.com)。
-
CDN 厂商在自己的权威 DNS 服务器上,根据请求来源的 LDNS IP 判断用户地理位置,返回就近节点的 A 记录。
这种「根据来源 IP 做智能调度」的机制被称为 GSLB(全局负载均衡)。这就是为什么同一个域名,在北京解析出的 IP 和在深圳解析出的 IP 可能完全不同。
3.7 DNS 的安全问题:劫持与污染
既然 DNS 是「问路」,那就存在「有人给你指错路」的风险:
-
DNS 劫持:攻击者篡改 DNS 响应,把用户导向钓鱼网站。常见的劫持发生在路由器、运营商或本地 hosts 文件层面。
-
DNS 污染:在请求到达权威服务器之前,攻击者抢先返回伪造的响应。因为 DNS 查询默认走 UDP 且明文传输,攻击者可以在真实响应到达前,抢先注入一个伪造的 IP 响应包,让客户端拿到错误结果。
对应的防护手段主要有 DNSSEC、DoT(DNS over TLS) 和 DoH(DNS over HTTPS)。DNSSEC 通过数字签名保证响应来源可信,DoT 和 DoH 则通过加密通道防止查询内容被篡改或窃听。这里还有一个常见的追问:DNS 为什么默认走 UDP?答案是它追求低延迟和高吞吐,单次查询报文通常很小,UDP 一次往返即可完成;但 UDP 报文长度受限,遇到大响应时会退化为 TCP 53 端口。
四、TCP 连接:从三次握手到可靠传输
拿到服务器 IP 之后,浏览器要开始建立真正的连接。如果你访问的是 HTTP 站点,下一步就是 TCP 三次握手;如果是 HTTPS 站点,则先完成 TCP 握手,再进行 TLS 握手。这一章我们先把 TCP 的底子打牢。
4.1 为什么 TCP 需要三次握手
三次握手的目的可以浓缩成一句话:双方都要确认自己的发送能力和对方的接收能力都正常。第一次握手确认了客户端的发送能力,第二次握手确认了服务端的发送能力和客户端的接收能力,第三次握手才最终确认了服务端的接收能力。
如果用两次握手,服务端在发出第二次握手包后,无法知道客户端是否真的收到了自己的响应,也就无法确认双方序列号是否同步成功。更严重的是,网络中存在延迟的历史连接请求,如果服务端收到一个已经过期的 SYN 就立刻建立连接,会造成资源浪费。三次握手通过让客户端最后确认一次,能够有效减少无效连接。
4.2 三次握手的完整过程
三次握手的交互流程如下:
-
第一次握手:客户端发送 SYN 包,随机生成初始序列号 seq=x,进入 SYN_SENT 状态。此时客户端明确自己可以发送数据。
-
第二次握手:服务端收到 SYN 后回复 SYN+ACK 包,确认号 ack=x+1,并生成自己的初始序列号 seq=y,进入 SYN_RCVD 状态,同时把该连接放入半连接队列。
-
第三次握手:客户端收到 SYN+ACK 后回复 ACK 包,确认号 ack=y+1,进入 ESTABLISHED 状态。服务端收到 ACK 后,将连接从半连接队列移入全连接队列,也进入 ESTABLISHED 状态。
可以用下面的时序图表示:
text
客户端 服务端 | ---- SYN, seq=x -----------> | | <--- SYN+ACK, seq=y, ack=x+1 -| | ---- ACK, ack=y+1 ---------> | | 连接建立 |
这里隐藏两个高频追问。第一,初始序列号为什么是随机的:如果序列号固定,攻击者容易预测下一个连接的序列号,进而伪造报文劫持会话。第二,SYN 队列和 SYN Flood 攻击:服务端收到 SYN 而未收到第三次握手前,连接会一直占用半连接队列。攻击者大量发送 SYN 而不完成握手,就会耗尽队列资源,这就是 SYN Flood。常见防御手段包括 SYN Cookie、限制半连接数量和流量清洗。
4.3 四次挥手与 TIME_WAIT
连接建立要三次握手,断开却要四次挥手,原因是 TCP 是全双工的,两个方向要分别关闭。四次挥手的过程是:
-
主动关闭方发送 FIN,表示自己不再发送数据。
-
被动关闭方回复 ACK,表示确认收到对方的关闭请求。
-
被动关闭方处理完剩余数据后,也发送 FIN。
-
主动关闭方回复 ACK,连接彻底关闭。
主动关闭方在发送最后一个 ACK 后会进入 TIME_WAIT 状态,等待 2MSL 时间。这不是 bug,而是为了确保最后一个 ACK 丢失时,对方能重发 FIN,同时让旧连接的迟到报文自然消失,避免影响新连接。面试中问「服务器上有大量 TIME_WAIT 怎么办」,可以回答调整内核参数(如 tcp_tw_reuse、缩短 TIME_WAIT 时间)或从架构上让客户端主动关闭连接。
4.4 可靠传输:序列号、确认应答与超时重传
TCP 的可靠性建立在三个机制上:
-
序列号与确认应答:每个字节数据都有编号,接收方通过 ACK 告诉发送方「期待的下一个字节序号」,保证数据有序且不丢失。
-
超时重传:发送方每发送一段数据就启动定时器,超时未收到确认就重传。超时时间会通过 RTT 动态估算,即 RTO。
-
快速重传:如果接收方连续收到三个相同 ACK(说明后续数据包乱序或丢失),发送方不必等超时就立即重传缺失的报文。
此外还有滑动窗口机制,它让发送方可以连续发送多个报文而不必等每个 ACK,从而提升吞吐。窗口大小由接收方的缓冲区决定,接收方通过 ACK 报文中的 Window 字段动态告知发送方。
4.5 拥塞控制:慢启动与快恢复
可靠传输解决的是「不丢」,拥塞控制解决的是「不把网络压垮」。TCP 通过四个算法动态调整发送窗口:
-
慢启动:连接刚建立时窗口很小,每收到一个 ACK 就把拥塞窗口翻倍,指数增长到慢启动阈值。
-
拥塞避免:窗口超过阈值后改为线性增长,每个 RTT 只增加一个报文段,避免过快占满带宽。
-
快重传:收到三个重复 ACK 时立即重传,而不是等待超时。
-
快恢复:快重传后不回到慢启动,而是把阈值减半后直接进入拥塞避免,快速恢复传输速率。
面试时如果能结合「为什么网速时快时慢」「为什么弱网下上传很吃力」来解释拥塞控制,会比只背名词更有说服力。
五、TLS 握手:HTTPS 的安全底座
现代网站几乎都运行在 HTTPS 上,所以「URL 输入到返回请求」这条链路里,TLS 握手是绕不开的一环。它不仅负责加密,还负责身份认证和完整性校验。
5.1 为什么需要 TLS
如果只有 TCP,数据是明文传输的,中间人可以轻松窃听、篡改甚至伪装。TLS(Transport Layer Security)在 TCP 之上提供三个核心能力:
-
机密性:通过对称加密保证通信内容不被第三方读取。
-
完整性:通过消息摘要或 MAC 保证内容没有被篡改。
-
身份认证:通过数字证书验证服务器身份,防止中间人伪装。
5.2 TLS 1.2 的握手过程
TLS 1.2 的完整握手需要两个 RTT,大致过程如下:
-
ClientHello:客户端发送支持的 TLS 版本、加密套件、随机数。
-
ServerHello:服务端选定加密套件,返回自己的随机数和数字证书。
-
证书验证:客户端验证证书链是否可信,确认服务端身份。
-
密钥协商:双方根据密钥交换算法协商出共享的会话密钥。传统 RSA 模式由客户端生成预主密钥并用服务端公钥加密;现代 ECDHE 模式则通过椭圆曲线临时密钥对实现前向保密。
-
完成确认:双方发送 Finished 消息,验证握手和加密通道是否正常。
面试中常问「RSA 和 ECDHE 的区别」,核心答案有两点:ECDHE 支持前向保密,即使服务端私钥泄露,历史会话也无法被解密;而 RSA 模式下会话密钥由客户端生成并用服务端公钥加密,一旦服务端私钥泄露,历史流量都能被解开。
5.3 TLS 1.3 的改进
TLS 1.3 做了大幅简化,握手缩短到 1 RTT,主要有三个变化:
-
删除不安全的算法:移除了 RSA 密钥交换、SHA-1、3DES 等过时方案,只保留安全性更高的算法。
-
握手更快:密钥协商提前到 ClientHello 阶段,减少一个往返。
-
0-RTT 模式:在会话恢复场景下,客户端可以在首次往返中就携带加密数据,进一步压低延迟。
5.4 会话恢复与性能优化
TLS 握手本身有一定成本,生产环境中常用两种方式复用会话参数:
-
Session ID:服务端缓存会话参数,客户端下次带上 Session ID 即可快速恢复。
-
Session Ticket:服务端把会话参数加密成 Ticket 交给客户端保存,恢复时无需服务端缓存,适合多节点架构。
如果能继续聊到「HTTPS 虽然加密,但 SNI 和证书握手阶段仍是明文」这个点,面试官会认为你确实理解 TLS 的实际约束。
六、HTTP 请求:报文、版本与状态
TCP 或 TLS 连接建立之后,浏览器终于可以发送真正的 HTTP 请求了。这一步看似简单,但报文结构、Cookie、版本差异和状态码都是面试重点。
6.1 HTTP 请求报文结构
一个典型的 HTTP/1.1 请求报文由请求行、请求头和可选的请求体组成:
text
GET /path/to/resource?key=value HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 Accept: text/html,application/xhtml+xml Accept-Encoding: gzip, deflate, br Connection: keep-alive Cookie: session_id=abc123
请求行包含方法、目标路径、协议版本。请求头中 Host 用于区分同一 IP 上的多个虚拟主机,Accept-Encoding 声明客户端支持的内容压缩方式,Cookie 携带客户端状态。
6.2 常用请求方法与幂等性
最常用的方法有 GET、POST、PUT、DELETE,其中前两个在面试中出现频率最高:
-
GET:获取资源,参数通常放在 URL 中,是幂等的,可被缓存。
-
POST:提交数据,参数放在请求体中,不是幂等的,一般不缓存。
这里要强调「幂等性」:GET、PUT、DELETE 是幂等的,重复调用不会产生额外副作用;POST 不是幂等的,重复提交可能创建多条记录。面试中「GET 和 POST 的区别」如果只回答「GET 在 URL 带参、POST 在 Body 带参」,实在太浅;再加上幂等性、缓存、语义和安全性差异,才算完整。
6.3 Cookie 与 Session
HTTP 本身是无状态的,Cookie 就是用来保存状态的方案。服务端通过 Set-Cookie 响应头把标识写进浏览器,浏览器后续请求自动携带回来。常见的属性包括:
-
HttpOnly:禁止 JS 读取,降低 XSS 攻击风险。
-
Secure:只在 HTTPS 下传输。
-
SameSite:限制跨站请求时是否携带,用于减轻 CSRF 攻击。
如果继续追问分布式下 Session 怎么共享,可以回答:粘性会话、独立 Session 服务、Redis 集中存储,以及更现代的 JWT Token 方案。
6.4 HTTP/1.1、HTTP/2 与 HTTP/3
不同版本的差异是面试高频点:
-
HTTP/1.1:默认长连接,但同一连接上的请求是串行的,浏览器通过开多个连接缓解队头阻塞。
-
HTTP/2:引入多路复用,所有请求可在一个 TCP 连接上并行;同时支持头部压缩、二进制分帧和服务端推送。但底层仍是 TCP,丢包仍然会导致整个连接上的流受影响。
-
HTTP/3:底层从 TCP 换成基于 UDP 的 QUIC,实现无队头阻塞、连接迁移和更快的握手,更适合弱网和移动场景。
6.5 状态码速记
掌握状态码的区间含义就足够应对大多数追问:
-
1xx:信息性,如 101 协议切换。
-
2xx:成功,如 200 请求成功、204 无内容。
-
3xx:重定向,如 301 永久重定向、302 临时重定向、304 缓存未过期。
-
4xx:客户端错误,如 400 参数错误、401 未认证、403 无权限、404 资源不存在。
-
5xx:服务端错误,如 500 服务器内部错误、502 网关错误、503 服务不可用、504 网关超时。
304 尤其值得展开:当浏览器携带缓存标识去访问时,服务端如果判断资源没变化,就返回 304 并不带回响应体,浏览器继续使用本地缓存,从而节省带宽。
七、负载均衡与反向代理
你访问的 www 域名后面,通常站着一整个集群,而不是单台服务器。请求从公网进来后,第一站往往是负载均衡器或反向代理。
7.1 为什么需要负载均衡
单台服务器的性能和可用性都有上限。负载均衡的核心价值有三个:
-
横向扩展:把流量分摊到多台机器,提升整体吞吐。
-
高可用:某台机器故障时自动摘除,不影响整体服务。
-
灵活运维:发布时可以先摘掉部分节点做灰度或滚动更新,减少停机。
7.2 常见的负载均衡算法
-
轮询:依次分配,实现简单,但不考虑机器负载差异。
-
加权轮询:为性能更高的机器配置更高权重。
-
随机:随机选择一台,配合权重效果类似加权轮询。
-
最少连接数:把请求分配给当前连接数最少的机器,适合长连接场景。
-
一致性哈希:根据请求特征(如用户 ID、IP)映射到固定节点,适合需要会话黏着或缓存命中的场景。
7.3 反向代理与网关
反向代理站在服务端一侧,接收公网请求并转发到内部服务器。除了负载均衡,它还承担:
-
SSL 卸载:由代理统一处理 HTTPS 加密解密,内网流量保持明文,降低后端压力。
-
安全防护:隐藏内部服务器拓扑,过滤恶意请求。
-
路由与灰度:按路径或 Header 把请求分流到不同服务版本。
常见实现有 Nginx、OpenResty、Envoy、HAProxy,以及云厂商提供的负载均衡服务。微服务架构中,还会在网关层叠加鉴权、限流、熔断、链路追踪等能力。
八、后端服务处理请求
请求到达后端后,会经历一系列处理,这一部分也是面试官最容易从「网络」切换到「后端工程」的地方。
8.1 从网关到应用服务
典型链路是:负载均衡 → API 网关 → 应用服务。网关负责统一的鉴权、限流、路由、日志,应用服务负责真正的业务逻辑。服务之间通过 RPC 或 HTTP 调用,也可能通过消息队列解耦。
8.2 应用层处理
应用服务收到请求后,通常按分层架构处理:
-
Controller 层:解析参数、校验、调用 Service。
-
Service 层:业务逻辑、事务边界、跨服务调用。
-
Repository 层:数据访问,可能走缓存、数据库、搜索引擎。
8.3 数据访问与缓存
数据访问是链路上最慢的一环,所以通常会叠加多级缓存:
-
本地缓存:Caffeine、Guava Cache,访问速度最快。
-
分布式缓存:Redis、Memcached,跨节点共享。
-
数据库:MySQL、PostgreSQL,最终一致性的落点。
如果继续追问缓存穿透、击穿、雪崩,可以结合具体业务场景说明防御方案。如果能提到「缓存与数据库的双写一致性」,说明你有实际工程经验。
8.4 事务与一致性
单库场景用本地事务即可,跨库场景需要引入分布式事务或最终一致性方案:
-
强一致:2PC/XA,性能差但一致性最强。
-
最终一致:TCC、Saga、本地消息表、事务消息、最大努力通知。
面试时如果能说出「业务上大多允许最终一致,所以实际项目中优先选柔性事务」这样的取舍,会非常加分。
九、响应返回与浏览器渲染
服务端处理完成后,响应会沿着原链路返回客户端,然后进入浏览器渲染阶段。
9.1 响应报文结构
响应报文包括状态行、响应头、响应体:
text
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Length: 12345 Cache-Control: max-age=3600 Set-Cookie: session_id=abc123; HttpOnly; Secure <html>...</html>
Content-Type 告诉浏览器如何解析响应体,Cache-Control 决定缓存策略,Content-Encoding 表示压缩方式。
9.2 浏览器渲染流程
浏览器拿到 HTML 后,会经历以下阶段:
-
解析 HTML:构建 DOM 树。
-
解析 CSS:构建 CSSOM 树。
-
合并渲染树:DOM + CSSOM 合并成 Render Tree。
-
布局:计算每个节点的位置和大小。
-
绘制:把节点绘制到图层。
-
合成:把图层合成为最终页面。
如果涉及 JS,还会遇到 JS 阻塞解析、异步加载、DOMContentLoaded 和 load 事件的区别等高频话题。
9.3 关键渲染路径优化
优化首屏渲染的常见手段包括:
-
减少关键资源数量:内联关键 CSS,异步加载非关键 JS。
-
使用 preload / prefetch:提前加载关键资源,预取后续资源。
-
开启 HTTP/2、HTTP/3:减少连接数,充分利用多路复用。
-
合理使用 CDN:静态资源就近分发。
-
启用 Gzip / Brotli 压缩:减少传输体积。
十、面试回答模板与高频追问
10.1 标准回答结构
如果把整条链路浓缩成一段回答,可以按以下五层递进:
-
浏览器处理:判断输入类型、URL 规范化、HSTS 改写、进程协作。
-
DNS 解析:缓存 → hosts → LDNS → 递归/迭代查询 → 拿到 IP。
-
建立连接:TCP 三次握手(HTTPS 再加 TLS 握手),协商加密通道。
-
发送请求:HTTP 报文、Cookie、请求方法、连接复用。
-
服务端处理与响应:负载均衡、网关、应用服务、缓存/数据库,返回响应后浏览器渲染。
每一层都能再往下挖三层,这就是深度。
10.2 高频追问清单
-
DNS 递归和迭代有什么区别?
-
为什么 TCP 是三次握手不是两次?
-
TIME_WAIT 为什么需要 2MSL?
-
TLS 1.2 和 TLS 1.3 握手有什么区别?
-
HTTP/2 相比 HTTP/1.1 有什么改进?
-
304 状态码如何触发?
-
反向代理和正向代理的区别?
-
分布式 Session 怎么共享?
-
缓存穿透、击穿、雪崩怎么处理?
-
浏览器输入 URL 后为什么有时候不是发 HTTP 请求?
10.3 最后总结
这道题真正的难点,不在于背出一长串流程,而在于:
-
结构化表达:把链路拆成清晰的阶段,每阶段先讲目的、再讲过程、最后讲异常。
-
工程视角:不只是理论,还要讲缓存、压缩、CDN、限流、灰度。
-
深度下钻:每个环节都能追三层,从 API 到协议再到操作系统。
-
闭环思维:从用户输入开始,到浏览器渲染结束,回答形成闭环。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)