🌐 HTTP协议基础
什么是HTTP?
HTTP(HyperText Transfer Protocol)超文本传输协议是互联网上应用最为广泛的一种网络协议。它是一个基于请求-响应模式的、无状态的应用层协议,常基于TCP协议传输。
OSI七层协议模型
1┌─────────────┐
2│ 应用层(7) │ ← HTTP/HTTPS/FTP/SMTP
3├─────────────┤
4│ 表示层(6) │ ← SSL/TLS加密
5├─────────────┤
6│ 会话层(5) │ ← 建立/管理/终止会话
7├─────────────┤
8│ 传输层(4) │ ← TCP/UDP
9├─────────────┤
10│ 网络层(3) │ ← IP
11├─────────────┤
12│ 数据链路层(2)│ ← 以太网
13├─────────────┤
14│ 物理层(1) │ ← 物理传输介质
15└─────────────┘
面试考点:能够清晰说出HTTP位于应用层,基于TCP协议,并理解各层的作用。
🚀 HTTP版本演进史
HTTP/0.9 (1991年) - 最简单的版本
特点:
- 只支持 GET 请求
- 没有请求头(Header)
- 只能传输 HTML文本
- 请求完成后立即关闭连接
1GET /index.html
面试考点:这是HTTP最初版本,功能极其简单,为后续版本奠定基础。
HTTP/1.0 (1996年) - 多媒体时代
核心改进:
- ✅ 引入了请求头和响应头
- ✅ 支持多种数据类型(图片、CSS、JS等)
- ✅ 引入了状态码概念
- ✅ 支持Cookie(但仍然是无状态协议)
1GET /image.jpg HTTP/1.0
2Host: www.example.com
3User-Agent: Mozilla/5.0
4Accept: image/jpeg, image/png
5
6HTTP/1.0 200 OK
7Content-Type: image/jpeg
8Content-Length: 12345
9Set-Cookie: session=abc123
10
11[二进制图片数据]
缺点:
- 每次请求都需要重新建立TCP连接
- 连接无法复用,性能开销大
HTTP/1.1 (1997年) - 长连接时代
重大改进:
1. 持久连接(Keep-Alive)
- 推出了长链接 -Connection: keep-alive
一个TCP可以处理多个请求,浏览器通过一个TCP连接连续请求 页面、图片、脚本等多个资源,服务器处理完不会立刻断开,而是 保持链接。后续请求无需重新建立链接,节省时间和性能开销, 提高加速速度。
1GET / HTTP/1.1
2Host: www.example.com
3Connection: keep-alive
4
5HTTP/1.1 200 OK
6Connection: keep-alive
7Keep-Alive: timeout=5, max=100
2. 管道化(Pipelining)
管道化 pipelining 允许同时发送多个请求 你用支持管道化的浏览器,依次发送 获取首页、图片1,图片2,无需等待前一个响应。但服务器必须按顺序返回。
- 允许在同一连接上并发发送多个请求
- 但响应必须按顺序返回
3. 分块传输编码
TCP 可靠的传输,一个通信的多个数据包,按顺序、全部到达浏览器。 没有能真正并发,TCP 安全 响应时还是顺序的传输 队头阻塞 如果排在前面的资源传输慢,后面的资源没办法传输
1HTTP/1.1 200 OK
2Transfer-Encoding: chunked
3
45\r\n
5Hello\r\n
66\r\n
7World!\r\n
80\r\n
9\r\n
存在问题:
- 队头阻塞:前面请求慢会阻塞后面请求
- 同域名并发限制:浏览器通常限制6个并发连接
HTTP/2.0 (2015年) - 多路复用时代
革命性改进:
1. 二进制分帧
- 二进制分帧 所有请求和响应都被拆成小数据帧,通过一个链接并发传输,每个帧带有编号, 制定是哪个文件,客户端和服务端可以根据编号,组装数据。 无需排队,谁先准备好谁就先发、解决了对头阻塞的问题。
1文本协议 → 二进制协议
2┌─────────────┐ ┌─────────────┐
3│ Header │ → │ Headers │
4│ Frame │ │ Frame │
5├─────────────┤ ├─────────────┤
6│ Data │ → │ Data │
7│ Frame │ │ Frame │
8└─────────────┘ └─────────────┘
2. 多路复用(Multiplexing)
- 并发 多路复用 一个TCP 链接上并发多个请求,不再队头阻塞。 多轮复用把数据拆分成多个帧,通过一个链接并发传输。
1HTTP/1.1: 一个连接同时只能处理一个请求
2┌─────┐ ┌─────┐ ┌─────┐
3│请求1 │ │请求2 │ │请求3 │
4└──┬──┘ └──┬──┘ └──┬──┘
5 │ 等待 │ 等待 │
6 ▼ ▼ ▼
7┌─────────────────────────┐
8│ 服务器 │
9└─────────────────────────┘
10
11HTTP/2.0: 一个连接可以并发处理多个请求
12┌─────┐ ┌─────┐ ┌─────┐
13│请求1 │ │请求2 │ │请求3 │
14└──┬──┘ └──┬──┘ └──┬──┘
15 │ 并发 │ 并发 │
16 ▼ ▼ ▼
17┌─────────────────────────┐
18│ 服务器 │
19└─────────────────────────┘
3. 头部压缩(HPACK)
- 头部压缩 减少重复header 传输。
- 使用HPACK算法压缩请求头
- 维护头部字段表,避免重复传输
4. 服务器推送(Server Push)
- 服务器端推送 server push 服务器端可主动推送资源。首页GET/返回很快,但首屏还依赖app.css app.js 等,为了减少首轮返回的时间,服务器端可以主动推送。
HTTP/3.0 (2020年) - QUIC时代
基于QUIC协议(UDP):
- 解决了TCP的队头阻塞问题
- 更快的连接建立
- 更好的移动网络支持
⚡怎么优化网页加载速度,在通信这块?
通信层面的网页加载优化策略
-
路由懒加载与分包
将应用按路由拆分为独立的模块(如Login.jsx
、App.jsx
),在用户访问对应页面时才按需加载,减少首屏体积,加快初始加载速度。 -
资源懒加载与请求优化
- 图片懒加载:只在用户视口范围内加载图片,避免一次性加载所有资源。
- 合并与压缩文件:将过多的 JS、CSS 文件进行合并与压缩,减少请求数与资源体积。
- 域名并发优化:浏览器对同一域名的并发请求通常限制在 6 个左右,可以通过配置多个静态资源域名来提升并发度。
-
减少 HTTP 请求
- 将小图标转为 Base64 并内嵌在 HTML/CSS 中,避免额外请求。
- 使用 图标字体库(IconFont) 代替多张小图片,提升复用性与加载效率。
-
开启传输压缩
启用 Gzip 或 Brotli 压缩,将 HTML、CSS、JS 等文本资源进行压缩传输,大幅减少数据体积。
🔍 GET vs POST 深度解析
基础区别对比表
特性 | GET | POST |
---|---|---|
用途 | 获取数据 | 提交数据 |
数据位置 | URL参数(Query String) | 请求体(Request Body) |
安全性 | 相对不安全(URL可见) | 相对安全(数据在请求体) |
缓存 | 可被缓存 | 通常不被缓存 |
书签 | 可保存书签 | 无法保存书签 |
数据长度 | 受URL长度限制(~2048字符) | 理论上无限制 |
幂等性 | 幂等(多次调用结果相同) | 非幂等(可能产生副作用) |
详细解析
1. 数据传输方式
GET请求示例:
1GET /search?q=HTTP&type=article HTTP/1.1
2Host: www.juejin.cn
3User-Agent: Mozilla/5.0
4Accept: text/html
POST请求示例:
1POST /api/login HTTP/1.1
2Host: www.juejin.cn
3Content-Type: application/json
4Content-Length: 45
5
6{
7 "username": "developer",
8 "password": "123456"
9}
2. RESTful API设计
1GET /api/users
2GET /api/users/123
3POST /api/users
4PUT /api/users/123
5PATCH /api/users/123
6DELETE /api/users/123
3. 安全性考虑
1GET /api/login?username=admin&password=123456
2
3
4POST /api/login
5Content-Type: application/json
6{
7 "username": "admin",
8 "password": "123456"
9}
10
11
12HTTPS POST /api/login
面试常见问题解答
Q: GET请求能否包含请求体? A: 技术上可以,但不推荐。RFC 7231没有禁止,但大多数服务器会忽略GET请求的请求体。
Q: POST就一定安全吗? A: 相对安全,但如果没有HTTPS加密,数据在网络传输中仍然是明文,可能被抓包工具截获。
🔒 HTTPS安全机制
HTTPS = HTTP + SSL/TLS
SSL/TLS握手过程
11. 客户端发送Client Hello
2 ├── 支持的TLS版本
3 ├── 支持的加密算法
4 └── 随机数1
5
62. 服务器发送Server Hello
7 ├── 选择的TLS版本
8 ├── 选择的加密算法
9 ├── 随机数2
10 └── 服务器证书
11
123. 客户端验证证书
13 ├── 检查证书有效性
14 ├── 生成预主密钥
15 └── 用服务器公钥加密发送
16
174. 双方生成会话密钥
18 ├── 基于两个随机数和预主密钥
19 └── 开始加密通信
HTTPS优势
- 数据加密:防止窃听
- 数据完整性:防止篡改
- 身份验证:防止冒充
- SEO友好:搜索引擎优先收录
混合加密原理
1对称加密 + 非对称加密 = 混合加密
2
3┌─────────────────┐ ┌─────────────────┐
4│ 非对称加密 │ │ 对称加密 │
5│ (握手阶段) │ → │ (数据传输) │
6│ 交换密钥 │ │ 高效加密 │
7└─────────────────┘ └─────────────────┘
🗄️ 浏览器缓存机制
缓存类型
1. 强缓存(Strong Cache)
1# Expires (HTTP/1.0)
2Expires: Wed, 21 Oct 2024 07:28:00 GMT
3
4# Cache-Control (HTTP/1.1)
5Cache-Control: max-age=3600
6Cache-Control: no-cache
7Cache-Control: no-store
8Cache-Control: must-revalidate
2. 协商缓存(Negotiation Cache)
1# 基于修改时间
2Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
3If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
4
5# 基于文件内容
6ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
7If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
缓存策略最佳实践
1const cacheStrategies = {
2
3 static: {
4 'Cache-Control': 'max-age=31536000',
5 'Expires': new Date(Date.now() + 31536000000).toUTCString()
6 },
7
8
9 dynamic: {
10 'Cache-Control': 'no-cache',
11 'ETag': generateETag(content)
12 },
13
14
15 sensitive: {
16 'Cache-Control': 'no-store'
17 }
18};
🌐 TCP/IP协议栈
TCP三次握手
1客户端 服务器
2 | |
3 | 1. SYN(seq=x) |
4 |───────────────────────>|
5 | |
6 | 2. SYN+ACK |
7 |<───────────────────────|
8 | (seq=y, ack=x+1) |
9 | |
10 | 3. ACK(ack=y+1) |
11 |───────────────────────>|
12 | |
13 | 连接建立成功 |
TCP四次挥手
1客户端 服务器
2 | |
3 | 1. FIN(seq=u) |
4 |───────────────────────>|
5 | |
6 | 2. ACK(ack=u+1) |
7 |<───────────────────────|
8 | |
9 | 3. FIN(seq=v) |
10 |<───────────────────────|
11 | |
12 | 4. ACK(ack=v+1) |
13 |───────────────────────>|
14 | |
15 | 连接关闭成功 |
TCP vs UDP对比
特性 | TCP | UDP |
---|---|---|
连接性 | 面向连接 | 无连接 |
可靠性 | 可靠传输,有确认机制 | 不可靠传输,无确认 |
速度 | 相对较慢 | 相对较快 |
头部开销 | 20字节 | 8字节 |
适用场景 | 文件传输、网页浏览 | 视频直播、DNS查询 |
📝 面试常见问题集锦
1. HTTP状态码详解
2xx成功
- 200 OK:请求成功
- 201 Created:资源创建成功
- 204 No Content:请求成功但无返回内容
3xx重定向
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 304 Not Modified:资源未修改,使用缓存
4xx客户端错误
- 400 Bad Request:请求语法错误
- 401 Unauthorized:未认证
- 403 Forbidden:无权限访问
- 404 Not Found:资源未找到
5xx服务器错误
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误
- 503 Service Unavailable:服务不可用
2. 高频面试题回答模板
Q1: 描述一下HTTP的发展历程?
参考回答:
HTTP,全称 HyperText Transfer Protocol,作为万维网的基石,它的发展历程大致可以分为以下几个阶段:
1. HTTP/0.9(1991 年)
- 最初的版本,非常简陋。
- 只支持 GET 请求,没有请求头和响应头。
- 返回的内容只能是 纯文本 HTML,无法传输图片、CSS、JS 等资源。
- 典型应用是传输简单的超文本页面。
2. HTTP/1.0(1996 年)
- 引入了 请求头(Header) ,开始支持多种数据类型(图片、视频、脚本等)。
- 支持 状态码、缓存机制、Content-Type、Cookie 等关键功能。
- 但依然是 短连接:每次请求都要重新建立 TCP 连接,效率低。
- 特点:丰富了协议功能,但性能不足。
3. HTTP/1.1(1997 年)
-
是使用最广泛的版本,直到今天很多网站仍在使用。
-
核心改进:
- 长连接(Connection: keep-alive) :一个 TCP 连接可以复用,避免频繁建立/断开连接。
- 管道化(Pipelining) :可以一次性发送多个请求,但响应仍需按顺序返回,容易造成队头阻塞。
- 分块传输(Chunked Transfer Encoding) :支持动态内容分块发送。
- 更完善的缓存机制(强缓存 + 协商缓存)。
-
问题:队头阻塞(Head-of-Line Blocking),同一连接上如果前面的响应慢,会阻塞后续请求。
4. HTTP/2(2015 年)
-
针对 1.1 的性能问题进行优化。
-
核心特性:
- 二进制分帧:所有请求/响应数据拆成帧,用二进制传输,更高效。
- 多路复用(Multiplexing) :一个 TCP 连接可以并行传输多个请求和响应,彻底解决了队头阻塞问题。
- 头部压缩(HPACK) :减少重复 Header 的传输开销。
- 服务器推送(Server Push) :服务器可主动下发资源(如 CSS、JS),减少首屏延迟。
5. HTTP/3(2019 年,基于 QUIC)
-
由于 HTTP/2 仍依赖 TCP,而 TCP 的丢包重传机制可能拖慢整个连接,于是引入了 QUIC 协议(基于 UDP)。
-
优势:
- 真正的多路复用,丢一个包不会阻塞所有请求。
- 0-RTT 建连,降低握手延迟,提升移动网络下的体验。
- 内置加密(TLS 1.3),默认更安全。
-
目前在 YouTube、Google、Facebook 等大型应用已广泛使用
Q2: 如何优化HTTP请求性能?
标准回答:
1可以从以下几个方面优化:
2
31. 减少请求次数:
4 - 合并CSS/JS文件
5 - 使用CSS Sprites
6 - 内联小图片(Base64)
7
82. 减少请求大小:
9 - 开启Gzip压缩
10 - 压缩图片
11 - 移除无用代码
12
133. 缓存策略:
14 - 合理设置Cache-Control
15 - 使用ETags
16 - CDN缓存
17
184. 连接优化:
19 - 使用HTTP/2
20 - 域名分片(HTTP/1.1)
21 - Keep-Alive长连接
22
235. 加载优化:
24 - 资源懒加载
25 - 关键资源优先加载
26 - 预加载重要资源
Q3: HTTPS的工作原理?
标准回答:
1HTTPS = HTTP + SSL/TLS,工作流程如下:
2
31. 握手阶段:
4 - 客户端发送支持的加密算法列表
5 - 服务器选择算法并发送数字证书
6 - 客户端验证证书,生成对称密钥
7 - 双方确认,开始加密通信
8
92. 数据传输:
10 - 使用协商好的对称密钥加密数据
11 - 保证数据的机密性、完整性、身份认证
12
133. 混合加密:
14 - 非对称加密交换密钥(RSA/ECC)
15 - 对称加密传输数据(AES)
16
17这样既保证了安全性,又兼顾了性能。
3. 代码实现示例
简单HTTP服务器实现
1const http = require('http');
2const url = require('url');
3
4const server = http.createServer((req, res) => {
5 const parsedUrl = url.parse(req.url, true);
6 const path = parsedUrl.pathname;
7 const method = req.method;
8
9
10 res.setHeader('Access-Control-Allow-Origin', '*');
11 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
12 res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
13
14
15 if (method === 'GET' && path === '/api/users') {
16 res.writeHead(200, { 'Content-Type': 'application/json' });
17 res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));
18 } else if (method === 'POST' && path === '/api/users') {
19 let body = '';
20 req.on('data', chunk => {
21 body += chunk.toString();
22 });
23 req.on('end', () => {
24 const userData = JSON.parse(body);
25 res.writeHead(201, { 'Content-Type': 'application/json' });
26 res.end(JSON.stringify({ message: 'User created', data: userData }));
27 });
28 } else {
29 res.writeHead(404, { 'Content-Type': 'text/plain' });
30 res.end('Not Found');
31 }
32});
33
34server.listen(3000, () => {
35 console.log('Server running on http://localhost:3000');
36});
前端HTTP请求封装
1class HttpClient {
2 constructor(baseURL = '') {
3 this.baseURL = baseURL;
4 this.interceptors = {
5 request: [],
6 response: []
7 };
8 }
9
10
11 interceptRequest(fn) {
12 this.interceptors.request.push(fn);
13 }
14
15
16 interceptResponse(fn) {
17 this.interceptors.response.push(fn);
18 }
19
20 async request(config) {
21
22 for (const interceptor of this.interceptors.request) {
23 config = await interceptor(config);
24 }
25
26 const { method = 'GET', url, data, headers = {} } = config;
27 const fullUrl = this.baseURL + url;
28
29 const requestInit = {
30 method,
31 headers: {
32 'Content-Type': 'application/json',
33 ...headers
34 }
35 };
36
37 if (data && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
38 requestInit.body = JSON.stringify(data);
39 }
40
41 try {
42 let response = await fetch(fullUrl, requestInit);
43
44
45 for (const interceptor of this.interceptors.response) {
46 response = await interceptor(response);
47 }
48
49 return response;
50 } catch (error) {
51 console.error('HTTP Request failed:', error);
52 throw error;
53 }
54 }
55
56 get(url, config = {}) {
57 return this.request({ ...config, method: 'GET', url });
58 }
59
60 post(url, data, config = {}) {
61 return this.request({ ...config, method: 'POST', url, data });
62 }
63
64 put(url, data, config = {}) {
65 return this.request({ ...config, method: 'PUT', url, data });
66 }
67
68 delete(url, config = {}) {
69 return this.request({ ...config, method: 'DELETE', url });
70 }
71}
72
73
74const api = new HttpClient('https://api.example.com');
75
76
77api.interceptRequest(async (config) => {
78 const token = localStorage.getItem('token');
79 if (token) {
80 config.headers = {
81 ...config.headers,
82 'Authorization': `Bearer ${token}`
83 };
84 }
85 return config;
86});
87
88
89api.interceptResponse(async (response) => {
90 if (!response.ok) {
91 const errorData = await response.json();
92 throw new Error(errorData.message || 'Request failed');
93 }
94 return response.json();
95});
96
97
98api.get('/users').then(users => console.log(users));
99api.post('/users', { name: 'John', email: 'john@example.com' });
🎯 总结
HTTP协议作为Web开发的基石,掌握其各版本特性、性能优化和安全机制对前端开发者来说至关重要。在面试中,不仅要了解基础概念,更要能够结合实际项目经验,展示对HTTP协议的深入理解。
面试准备建议:
- 理论基础要扎实:HTTP各版本特性、TCP/UDP区别、缓存机制
- 实践经验要丰富:能结合项目讲述性能优化实践
- 前沿技术要了解:HTTP/3、QUIC协议等新技术发展
- 问题回答要结构化:先讲原理,再举例子,最后总结