前端网络相关知识深度解析
基于2024年最新技术发展的前端网络知识全面总结
目录
- 浏览器输入URL到页面展示的完整过程
- DNS域名解析系统
- HTTP协议详解
- HTTPS与安全传输
- TCP/UDP传输层协议
- 浏览器缓存机制
- CDN内容分发网络
- WebSocket实时通信
- 网络性能优化
- 安全防护机制
浏览器输入URL到页面展示的完整过程
🎆 完整流程图
1. URL解析与验证
输入处理阶段:
ini
用户输入: https://www.example.com/path?query=value#fragment
详细解析流程:
1.1 URL语法分析
javascript
// 浏览器内部URL解析伪代码
function parseURL(inputURL) {
const urlPattern = /^(([^:/?#]+):)?((\/\/([^/?#]*))?)([^?#]*)(\?([^#]*))?(#(.*))?$/;
const match = inputURL.match(urlPattern);
return {
protocol: match[2] || 'http', // https
host: match[5] || '', // www.example.com
pathname: match[6] || '/', // /path
search: match[8] || '', // query=value
hash: match[10] || '' // fragment
};
}
1.2 协议处理机制
diff
HTTP/HTTPS协议选择:
- HTTP:明文传输,默认80端口,无加密
- HTTPS:加密传输,默认443端口,TLS/SSL加密
- HTTP/2:二进制协议,多路复用,服务器推送
- HTTP/3:基于QUIC,UDP传输,0-RTT连接
1.3 域名规范化
- IDN处理:国际化域名转换为Punycode
- 大小写统一:域名转换为小写
- 尾点处理:移除或添加根域点
- 子域名解析:www前缀处理
1.4 路径与参数处理
javascript
// URL编码处理
function processURLComponents(url) {
// 路径编码(RFC 3986)
const encodedPath = encodeURIComponent(url.pathname);
// 查询参数解析
const queryParams = new URLSearchParams(url.search);
// 锚点处理(不发送到服务器)
const fragment = url.hash.substring(1);
return { encodedPath, queryParams, fragment };
}
特殊字符处理规则:
less
保留字符: : / ? # [ ] @
非保留字符: A-Z a-z 0-9 - . _ ~
需要编码: 空格(%20) 中文字符 特殊符号
2. 浏览器缓存检查
缓存查找顺序:
详细检查流程:
javascript
// 缓存检查伪代码
function checkCache(url) {
// 1. 检查Service Worker缓存
if (serviceWorkerCache.has(url)) {
return serviceWorkerCache.get(url);
}
// 2. 检查内存缓存
if (memoryCache.has(url)) {
return memoryCache.get(url);
}
// 3. 检查磁盘缓存
if (diskCache.has(url)) {
const cached = diskCache.get(url);
if (cached.expiry > Date.now()) {
return cached.data;
}
}
// 4. 缓存未命中,需要网络请求
return null;
}
3. DNS域名解析
完整解析流程:
3.1 缓存查找层次
javascript
// DNS缓存检查伪代码
class DNSResolver {
constructor() {
this.browserCache = new Map(); // 浏览器缓存(60秒)
this.osCache = new Map(); // 操作系统缓存
this.routerCache = new Map(); // 路由器缓存
this.ispCache = new Map(); // ISP缓存
}
async resolve(domain) {
// 1. 浏览器缓存检查
if (this.browserCache.has(domain)) {
const cached = this.browserCache.get(domain);
if (cached.expiry > Date.now()) {
console.log('命中浏览器缓存');
return cached.ip;
}
}
// 2. 操作系统缓存检查
if (this.osCache.has(domain)) {
console.log('命中系统缓存');
return this.osCache.get(domain).ip;
}
// 3. hosts文件检查
const hostsResult = this.checkHostsFile(domain);
if (hostsResult) {
console.log('命中hosts文件映射');
return hostsResult;
}
// 4. 进行递归查询
return await this.recursiveQuery(domain);
}
checkHostsFile(domain) {
// 检查 C:\Windows\System32\drivers\etc\hosts (在Windows系统中)
const hostsEntries = {
'localhost': '127.0.0.1',
'example.local': '192.168.1.100'
};
return hostsEntries[domain] || null;
}
}
3.2 递归查询详细过程
8.8.8.8"] B --> C{{"🌍 根DNS服务器
(.)"}} C --> D["📝 返回.com TLD服务器地址"] D --> E{{"🏬 顶级域名服务器
(.com)"}} E --> F["📝 返回example.com权威服务器地址"] F --> G{{"⚙️ 权威DNS服务器
(example.com)"}} G --> H["✅ 返回www.example.com的A记录"] H --> I["🎯 最终IP地址: 192.0.2.1"] classDef client fill:#e3f2fd,stroke:#1976d2,stroke-width:2px classDef dns fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px classDef result fill:#e8f5e8,stroke:#4caf50,stroke-width:2px class A,B client class C,E,G dns class D,F,H,I result
递归解析实现:
javascript
async function recursiveQuery(domain) {
// 步骤1:查询根DNS服务器
const rootServers = [
'198.41.0.4', // a.root-servers.net
'199.9.14.201', // b.root-servers.net
'192.33.4.12' // c.root-servers.net
];
let response = await queryDNS(rootServers[0], domain, 'NS');
// 步骤2:查询TLD服务器(.com)
const tldServers = response.authority; // [来自根服务器的TLD地址]
response = await queryDNS(tldServers[0], domain, 'NS');
// 步骤3:查询权威服务器
const authServers = response.authority; // [来自TLD的权威服务器地址]
response = await queryDNS(authServers[0], domain, 'A');
return response.answer[0].ip; // 返回最终IP地址
}
3.3 DNS记录类型深度解析
A记录(IPv4地址映射)
dns
www.example.com. 3600 IN A 192.0.2.1
字段说明:
- www.example.com.: 完整域名(FQDN)
- 3600: TTL(生存时间,秒)
- IN: Internet类别
- A: 记录类型
- 192.0.2.1: IPv4地址
AAAA记录(IPv6地址映射)
dns
www.example.com. 3600 IN AAAA 2001:db8:85a3::8a2e:370:7334
用途:
- 支持IPv6访问
- 提供更大地址空间
- 提高网络性能
CNAME记录(别名映射)
dns
www.example.com. 3600 IN CNAME example.com.
使用场景:
- CDN加速:www.example.com -> cdn.provider.com
- 负载均衡:api.example.com -> lb.example.com
- 服务迁移:old.example.com -> new.example.com
限制:
- CNAME记录不能与其他记录类型共存
- 最多5层CNAME跳转防止死循环
MX记录(邮件交换)
dns
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
优先级规则:
- 数字越小优先级越高
- 相同优先级随机选择(负载均衡)
- 支持邮件服务器备份
TXT记录(文本信息)
dns
example.com. 3600 IN TXT "v=spf1 include:_spf.google.com ~all"
example.com. 3600 IN TXT "google-site-verification=abc123def456"
应用场景:
1. SPF记录:防止邮件伪造
2. DKIM签名:邮件身份验证
3. 域名验证:证明域名所有权
4. 安全策略:CSP、HSTS等
3.4 DNS安全机制
DNSSEC(DNS安全扩展)
javascript
// DNSSEC验证流程
class DNSSECValidator {
validateChain(domain) {
// 1. 检查根域签名
const rootKey = this.getTrustAnchor();
// 2. 验证.com的DS记录
const comDS = this.verifyDS('.com', rootKey);
// 3. 验证example.com的DS记录
const exampleDS = this.verifyDS('example.com', comDS.key);
// 4. 验证www.example.com的A记录
const aRecord = this.verifyRRSIG('www.example.com', 'A', exampleDS.key);
return aRecord.verified;
}
verifyRRSIG(domain, type, publicKey) {
// RRSIG签名验证逻辑
const rrsig = this.getRRSIG(domain, type);
const signature = rrsig.signature;
const data = this.canonicalizeData(rrsig.data);
return crypto.verify(publicKey, data, signature);
}
}
DNS over HTTPS (DoH)实现:
javascript
class SecureDNSResolver {
constructor() {
this.dohServers = [
'https://cloudflare-dns.com/dns-query',
'https://dns.google/dns-query',
'https://dns.quad9.net/dns-query'
];
}
async resolve(domain, type = 'A') {
const query = {
name: domain,
type: type,
cd: false, // checking disabled
do: true // DNSSEC OK
};
try {
const response = await fetch(this.dohServers[0], {
method: 'POST',
headers: {
'Content-Type': 'application/dns-json',
'Accept': 'application/dns-json'
},
body: JSON.stringify(query)
});
const result = await response.json();
if (result.Status === 0) { // NOERROR
return this.parseAnswer(result.Answer);
} else {
throw new Error(`DNS query failed: ${result.Status}`);
}
} catch (error) {
console.error('DoH query failed:', error);
// 回退到传统DNS
return this.fallbackToTraditionalDNS(domain, type);
}
}
parseAnswer(answers) {
return answers.map(answer => ({
name: answer.name,
type: answer.type,
ttl: answer.TTL,
data: answer.data
}));
}
}
DNS记录类型:
swift
A记录: 域名 → IPv4地址
AAAA记录: 域名 → IPv6地址
CNAME记录: 域名 → 别名域名
MX记录: 邮件交换记录
TXT记录: 文本记录(如SPF、DKIM)
NS记录: 名称服务器记录
4. 建立TCP连接
三次握手详细过程:
ini
客户端 服务器
| |
| SYN seq=x → | 第一次握手
| |
| ← SYN+ACK seq=y,ack=x+1 | 第二次握手
| |
| ACK ack=y+1 → | 第三握手
| |
| 连接建立成功 |
每次握手的作用:
- 第一次握手:客户端证明自己的发送能力正常
- 第二次握手:服务器证明自己的接收和发送能力正常
- 第三次握手:客户端证明自己的接收能力正常,确认服务器的发送能力
TCP连接参数:
makefile
最大段大小(MSS): 1460字节
窗口大小: 65535字节
超时重传: 指数退避算法
拥塞控制: 慢启动 + 拥塞避免
5. TLS/SSL握手(HTTPS)
完整TLS 1.3握手流程:
yaml
客户端 服务器
| |
| ClientHello → | 1. 客户端问候
| - 支持的密码套件 |
| - 随机数1 |
| - 支持的TLS版本 |
| |
| ← ServerHello | 2. 服务器响应
| - 选择的密码套件 |
| - 随机数2 |
| - 服务器证书 |
| - 服务器密钥交换 |
| |
| 客户端密钥交换 → | 3. 密钥交换
| ChangeCipherSpec |
| Finished |
| |
| ← ChangeCipherSpec | 4. 握手完成
| ← Finished |
| |
| 加密通信开始 |
证书验证过程:
- 证书链验证:验证从网站证书到根CA的完整链
- 有效期检查:确认证书在有效期内
- 域名匹配:验证证书中的域名与访问域名一致
- 吊销检查:通过OCSP或CRL检查证书是否被吊销
- 签名验证:验证CA的数字签名
6. HTTP请求构建
HTTP/1.1请求报文结构:
http
GET /path?query=value HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cache-Control: max-age=0
If-None-Match: "abc123"
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
请求头详解:
- Host:目标主机名(HTTP/1.1必需)
- User-Agent:浏览器标识信息
- Accept:可接受的内容类型
- Accept-Encoding:支持的压缩算法
- Connection:连接管理(keep-alive/close)
- Cache-Control:缓存控制指令
- Authorization:身份认证信息
- Referer:来源页面URL
7. 服务器处理请求
服务器端处理流程:
7.1 Web服务器层
Nginx/Apache → 解析请求 → 路由匹配 → 静态/动态分发
7.2 应用服务器层
Node.js/Java/Python → 业务逻辑处理 → 数据库查询 → 响应构建
7.3 数据处理
sql
-- 示例数据库查询
SELECT title, content, created_at
FROM articles
WHERE id = ? AND status = 'published'
响应构建过程:
javascript
// 服务器响应构建示例
function buildResponse(request) {
const response = {
statusCode: 200,
headers: {
'Content-Type': 'text/html; charset=utf-8',
'Content-Encoding': 'gzip',
'Cache-Control': 'public, max-age=3600',
'ETag': '"def456"',
'Last-Modified': new Date().toUTCString(),
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
'X-XSS-Protection': '1; mode=block'
},
body: compressedHtmlContent
};
return response;
}
8. HTTP响应传输
HTTP/1.1响应报文结构:
http
HTTP/1.1 200 OK
Date: Thu, 22 Oct 2024 15:30:00 GMT
Server: nginx/1.20.2
Content-Type: text/html; charset=utf-8
Content-Length: 12345
Content-Encoding: gzip
Cache-Control: public, max-age=3600
ETag: "def456"
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains
Connection: keep-alive
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1>Welcome</h1>
<script src="/js/app.js"></script>
</body>
</html>
响应状态码分类:
diff
1xx 信息性状态码:
- 100 Continue: 继续请求
- 101 Switching Protocols: 切换协议
2xx 成功状态码:
- 200 OK: 请求成功
- 201 Created: 资源创建成功
- 204 No Content: 成功但无内容
- 206 Partial Content: 部分内容(断点续传)
3xx 重定向状态码:
- 301 Moved Permanently: 永久重定向
- 302 Found: 临时重定向
- 304 Not Modified: 资源未修改
- 307 Temporary Redirect: 临时重定向(保持方法)
4xx 客户端错误:
- 400 Bad Request: 请求语法错误
- 401 Unauthorized: 需要认证
- 403 Forbidden: 拒绝访问
- 404 Not Found: 资源不存在
- 405 Method Not Allowed: 方法不允许
- 429 Too Many Requests: 请求过多
5xx 服务器错误:
- 500 Internal Server Error: 服务器内部错误
- 502 Bad Gateway: 网关错误
- 503 Service Unavailable: 服务不可用
- 504 Gateway Timeout: 网关超时
9. 浏览器接收和解析
资源下载优先级:
markdown
1. 关键资源(HTML、Critical CSS)
2. 预加载资源(<link rel="preload">)
3. 样式表文件
4. 同步脚本
5. 异步脚本和图片
6. 延迟加载资源
HTML解析过程:
javascript
// HTML解析流程
function parseHTML(htmlContent) {
// 1. 词法分析(Tokenization)
const tokens = tokenizer.parse(htmlContent);
// 2. 构建DOM树
const domTree = domBuilder.build(tokens);
// 3. 样式计算
const cssRules = styleCalculator.compute(domTree);
// 4. 布局计算
const layoutTree = layoutCalculator.calculate(domTree, cssRules);
// 5. 绘制准备
const paintLayers = paintPreparer.prepare(layoutTree);
return {
dom: domTree,
css: cssRules,
layout: layoutTree,
paint: paintLayers
};
}
10. 资源加载与渲染
浏览器渲染管道:
css
HTML → DOM树
↓
CSS → CSSOM树
↓
DOM + CSSOM → 渲染树
↓
布局(Layout/Reflow)
↓
绘制(Paint)
↓
合成(Composite)
关键渲染路径优化:
html
<!-- 关键CSS内联 -->
<style>
.critical { font-size: 16px; color: #333; }
</style>
<!-- 预加载关键资源 -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/css/critical.css" as="style">
<!-- 异步加载非关键CSS -->
<link rel="preload" href="/css/non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<!-- 延迟加载脚本 -->
<script defer src="/js/app.js"></script>
<script async src="/js/analytics.js"></script>
DNS域名解析系统
DNS系统架构
分层结构:
DNS记录类型详解:
A记录(IPv4地址)
makefile
www.example.com. IN A 192.168.1.100
TTL: 3600秒
用途: 将域名指向IPv4地址
AAAA记录(IPv6地址)
yaml
www.example.com. IN AAAA 2001:db8::1
TTL: 3600秒
用途: 将域名指向IPv6地址
CNAME记录(别名)
makefile
www.example.com. IN CNAME example.com.
TTL: 3600秒
用途: 域名别名,不能与其他记录类型共存
MX记录(邮件交换)
makefile
example.com. IN MX 10 mail.example.com.
优先级: 10(数字越小优先级越高)
用途: 指定邮件服务器
TXT记录(文本信息)
makefile
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
用途: SPF、DKIM、域名验证等
DNS查询类型
递归查询
迭代查询
DNS缓存机制
缓存层级:
javascript
// DNS缓存层级示例
const dnsCache = {
// 浏览器缓存(60秒)
browser: {
'www.example.com': {
ip: '192.168.1.100',
ttl: 60,
timestamp: Date.now()
}
},
// 操作系统缓存(系统配置)
os: {
'www.example.com': {
ip: '192.168.1.100',
ttl: 3600,
timestamp: Date.now()
}
},
// 本地DNS服务器缓存(TTL配置)
localDNS: {
'www.example.com': {
ip: '192.168.1.100',
ttl: 86400,
timestamp: Date.now()
}
}
};
DNS安全
DNS劫持防护
javascript
// DNS over HTTPS (DoH) 实现
class SecureDNS {
constructor() {
this.dohServer = 'https://cloudflare-dns.com/dns-query';
}
async resolve(domain) {
const query = {
name: domain,
type: 'A'
};
const response = await fetch(this.dohServer, {
method: 'POST',
headers: {
'Content-Type': 'application/dns-json'
},
body: JSON.stringify(query)
});
return response.json();
}
}
DNSSEC验证
markdown
域名签名验证流程:
1. 权威DNS服务器使用私钥对DNS记录签名
2. 公钥通过DS记录发布到父域
3. 递归解析器验证签名链的完整性
4. 确保DNS响应未被篡改
HTTP协议详解
HTTP/1.1特性
持久连接(Keep-Alive)
http
# 请求头
Connection: keep-alive
Keep-Alive: timeout=5, max=100
# 响应头
Connection: keep-alive
Keep-Alive: timeout=5, max=100
优势:
- 减少TCP连接建立的开销
- 降低服务器资源消耗
- 提高页面加载速度
问题:
- 队头阻塞(Head-of-Line Blocking)
- 并发限制(浏览器对同一域名通常限制6个连接)
管道化(Pipelining)
性能对比:
- 传统模式:串行处理,总时间 = 6个时间单位
- 管道化模式:并行发送,总时间 = 6个时间单位(但网络利用率更高)
HTTP/2协议
二进制分帧
ini
HTTP/1.1 文本协议:
GET /index.html HTTP/1.1\r\n
Host: example.com\r\n
\r\n
HTTP/2 二进制帧:
[Length][Type][Flags][Stream ID][Payload]
[ 3 ][ 1 ][ 1 ][ 4 ][ N ]
多路复用
javascript
// HTTP/2 多路复用示例
class HTTP2Connection {
constructor() {
this.streams = new Map();
this.nextStreamId = 1;
}
createStream(request) {
const streamId = this.nextStreamId;
this.nextStreamId += 2; // 客户端使用奇数ID
const stream = {
id: streamId,
state: 'idle',
request: request,
response: null,
headers: new Map(),
data: []
};
this.streams.set(streamId, stream);
return stream;
}
sendFrame(streamId, type, flags, payload) {
const frame = {
length: payload.length,
type: type,
flags: flags,
streamId: streamId,
payload: payload
};
this.connection.write(this.encodeFrame(frame));
}
}
服务器推送
javascript
// 服务器推送实现
app.get('/index.html', (req, res) => {
// 推送CSS文件
res.push('/css/style.css', {
request: {
'accept': 'text/css'
},
response: {
'content-type': 'text/css'
}
});
// 推送JavaScript文件
res.push('/js/app.js', {
request: {
'accept': 'application/javascript'
},
response: {
'content-type': 'application/javascript'
}
});
// 发送HTML响应
res.send(htmlContent);
});
头部压缩(HPACK)
yaml
HTTP/1.1 重复头部:
GET /page1 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0...
Accept: text/html...
GET /page2 HTTP/1.1
Host: example.com # 重复
User-Agent: Mozilla/5.0... # 重复
Accept: text/html... # 重复
HTTP/2 HPACK压缩:
静态表 + 动态表 + 哈夫曼编码
头部大小减少约85%
HTTP/3协议深度解析
QUIC协议核心特性
1. 基于UDP的传输层
ini
传统模式:
HTTP/1.1: TCP + TLS 1.2 = 3-4 RTT
HTTP/2: TCP + TLS 1.2 = 3-4 RTT
HTTP/3模式:
HTTP/3: UDP + QUIC + TLS 1.3 = 1-2 RTT
首次连接:1 RTT
重连:0 RTT(使用缓存的连接状态)
2. 0-RTT连接建立
javascript
// QUIC 0-RTT实现原理
class QUICConnection {
constructor() {
this.cachedParams = null;
this.sessionTicket = null;
}
async connect(server, useCache = false) {
if (useCache && this.sessionTicket) {
// 0-RTT: 直接发送应用数据
const earlyData = this.buildEarlyDataPacket();
await this.sendPacket(server, earlyData);
console.log('0-RTT连接已建立');
return 'connected';
} else {
// 1-RTT: 正常握手流程
const clientHello = this.buildClientHello();
const serverResponse = await this.sendPacket(server, clientHello);
// 缓存会话信息供下次使用
this.sessionTicket = serverResponse.sessionTicket;
this.cachedParams = serverResponse.transportParams;
console.log('1-RTT连接已建立');
return 'connected';
}
}
buildEarlyDataPacket() {
return {
type: 'early_data',
sessionTicket: this.sessionTicket,
applicationData: 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n'
};
}
}
3. 流级别多路复用
javascript
// QUIC流管理
class QUICStreamManager {
constructor() {
this.streams = new Map();
this.nextStreamId = 0;
}
createStream(priority = 'normal') {
const streamId = this.nextStreamId;
this.nextStreamId += 4; // 客户端使用偶数ID
const stream = {
id: streamId,
priority: priority,
state: 'open',
sendBuffer: [],
receiveBuffer: [],
flowControlWindow: 65536 // 64KB
};
this.streams.set(streamId, stream);
return stream;
}
// 流级别隔离 - 一个流的错误不影响其他流
handleStreamError(streamId, error) {
const stream = this.streams.get(streamId);
if (stream) {
stream.state = 'error';
stream.error = error;
// 只重传当前流的数据
this.retransmitStream(streamId);
console.log(`流 ${streamId} 发生错误,但不影响其他流`);
}
}
retransmitStream(streamId) {
const stream = this.streams.get(streamId);
if (stream && stream.sendBuffer.length > 0) {
// 重传未确认的数据包
console.log(`重传流 ${streamId} 的数据`);
}
}
}
4. 内置加密与连接迁移
javascript
// QUIC连接迁移支持
class QUICMigration {
constructor() {
this.connectionId = this.generateConnectionId();
this.currentPath = null;
this.alternatePaths = [];
}
// 网络切换时的连接迁移
async migrateConnection(newInterface) {
console.log('检测到网络接口变化,开始连接迁移');
// 1. 在新接口上发送探测包
const probePacket = {
type: 'path_challenge',
connectionId: this.connectionId,
challenge: this.generateChallenge()
};
try {
const response = await this.sendOnNewPath(newInterface, probePacket);
if (response.type === 'path_response') {
// 2. 新路径可用,切换连接
this.currentPath = newInterface;
console.log('连接迁移成功,继续传输数据');
// 3. 通知应用层连接仍然有效
this.notifyApplicationLayerMigrationComplete();
}
} catch (error) {
console.log('连接迁移失败,保持原连接');
}
}
generateConnectionId() {
// 生成唯一连接ID,用于识别连接而非四元组
return crypto.randomBytes(8).toString('hex');
}
}
HTTP/3性能优势
1. 消除队头阻塞
less
HTTP/2 TCP队头阻塞问题:
流A: [1][2][X][4][5] // 包3丢失
流B: [1][2][3][4][5] // 受流A影响,全部阻塞
HTTP/3 QUIC解决方案:
流A: [1][2][X][4][5] // 只重传流A的包3
流B: [1][2][3][4][5] // 正常传输,不受影响
2. 更高效的拥塞控制
javascript
// QUIC拥塞控制算法
class QUICCongestionControl {
constructor() {
this.congestionWindow = 10; // 初始拥塞窗口
this.slowStartThreshold = 65535;
this.rtt = 100; // 初始 RTT (ms)
this.algorithm = 'cubic'; // 默认使用 CUBIC
}
onPacketAcked(packetSize, ackTime) {
// 更新 RTT
this.updateRTT(ackTime);
if (this.congestionWindow < this.slowStartThreshold) {
// 慢启动阶段:指数增长
this.congestionWindow += packetSize;
} else {
// 拥塞避免阶段:QUIC使用改进CUBIC算法
this.cubicUpdate(packetSize);
}
}
onPacketLost() {
// 检测到丢包
this.slowStartThreshold = this.congestionWindow / 2;
this.congestionWindow = this.slowStartThreshold;
console.log(`检测到丢包,拥塞窗口调整为: ${this.congestionWindow}`);
}
cubicUpdate(packetSize) {
// CUBIC算法实现(简化版)
const timeSinceLastLoss = Date.now() - this.lastLossTime;
const k = Math.cbrt(this.lastMaxWindow * 0.7 / 0.4); // CUBIC参数
const cubicWindow = 0.4 * Math.pow(timeSinceLastLoss - k, 3) + this.lastMaxWindow;
this.congestionWindow = Math.max(this.congestionWindow + packetSize / this.congestionWindow, cubicWindow);
}
}
3. 更好的流控制
javascript
// QUIC流控制机制
class QUICFlowControl {
constructor() {
this.connectionWindow = 1048576; // 1MB 连接级流控制
this.streamWindows = new Map(); // 流级流控制
}
canSendData(streamId, dataSize) {
const streamWindow = this.streamWindows.get(streamId) || 65536;
// 检查连接级和流级流控制
if (this.connectionWindow >= dataSize && streamWindow >= dataSize) {
// 更新窗口大小
this.connectionWindow -= dataSize;
this.streamWindows.set(streamId, streamWindow - dataSize);
return true;
}
return false;
}
updateWindow(streamId, windowUpdate) {
// 接收到窗口更新消息
if (streamId === 0) {
// 连接级窗口更新
this.connectionWindow += windowUpdate;
} else {
// 流级窗口更新
const currentWindow = this.streamWindows.get(streamId) || 0;
this.streamWindows.set(streamId, currentWindow + windowUpdate);
}
}
}
HTTP方法详解
GET请求
http
GET /api/users?page=1&limit=10 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
特点:
- 幂等操作
- 可缓存
- 参数在URL中
- 长度限制(约2048字符)
POST请求
http
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 95
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
{
"name": "John Doe",
"email": "john@example.com",
"role": "user"
}
特点:
- 非幂等操作
- 不可缓存
- 参数在请求体中
- 无长度限制
PUT请求(幂等更新)
http
PUT /api/users/123 HTTP/1.1
Host: api.example.com
Content-Type: application/json
If-Match: "abc123"
{
"name": "John Smith",
"email": "john.smith@example.com",
"role": "admin"
}
PATCH请求(部分更新)
http
PATCH /api/users/123 HTTP/1.1
Host: api.example.com
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/name", "value": "John Smith" },
{ "op": "add", "path": "/phone", "value": "+1234567890" }
]
DELETE请求
http
DELETE /api/users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
HTTPS与安全传输
TLS 1.3握手过程
1-RTT握手流程:
主要改进:
- 1-RTT握手(相比TLS 1.2的2-RTT)
- 移除不安全密码套件
- 强制前向保密性
- 0-RTT早期数据支持
数字证书验证
验证步骤:
- 有效期检查:证书在有效期内
- 域名匹配:CN或SAN字段匹配访问域名
- 证书链验证:从网站证书到根CA的完整链
- 撤销检查:通过OCSP或CRL检查
- 签名验证:验证CA的数字签名
TCP/UDP传输层协议
TCP三次握手详解
为什么需要三次?
- 防止旧的SYN请求建立错误连接
- 确认双方收发能力正常
- 避免半连接攻击
TCP四次挥手
TIME-WAIT状态作用:
- 确保ACK被正确接收
- 防止旧连接数据干扰新连接
TCP拥塞控制
四种算法:
- 慢启动:指数增长探测带宽
- 拥塞避免:线性增长维持稳定
- 快重传:收到3个重复ACK立即重传
- 快恢复:避免慢启动的性能损失
浏览器缓存机制
缓存分类
按位置分类:
java
1. Service Worker Cache (最高优先级)
2. Memory Cache (内存缓存)
3. Disk Cache (磁盘缓存)
4. Push Cache (HTTP/2推送缓存)
按类型分类:
markdown
1. 强缓存 (不发请求)
2. 协商缓存 (发请求验证)
强缓存机制
Cache-Control指令:
http
Cache-Control: public, max-age=3600, must-revalidate
指令说明:
- public: 可被任何缓存存储
- private: 只能被浏览器缓存
- max-age: 缓存有效期(秒)
- no-cache: 必须验证后使用
- no-store: 不得缓存
- must-revalidate: 过期后必须验证
协商缓存机制
ETag验证:
http
# 首次请求响应
ETag: "abc123"
# 再次请求
If-None-Match: "abc123"
# 服务器响应
HTTP/1.1 304 Not Modified # 未修改
# 或
HTTP/1.1 200 OK # 已修改,返回新内容
ETag: "def456"
CDN内容分发网络
CDN工作原理
请求流程:
CDN优化策略
1. 资源优化:
- 图片压缩与格式转换
- CSS/JS压缩与合并
- Gzip/Brotli压缩
2. 智能路由:
- 地理位置就近分配
- 网络质量检测
- 负载均衡
WebSocket 实时通信深度解析
WebSocket 连接建立过程
1. HTTP 升级协议握手
http
# 客户端发起升级请求
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: chat, superchat
Origin: https://example.com
# 服务器响应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
2. WebSocket 安全验证
javascript
// WebSocket 安全验证机制
function validateWebSocketHandshake(request) {
const websocketKey = request.headers['sec-websocket-key'];
const websocketVersion = request.headers['sec-websocket-version'];
// 1. 验证 WebSocket 版本
if (websocketVersion !== '13') {
throw new Error('不支持的 WebSocket 版本');
}
// 2. 验证 Sec-WebSocket-Key
if (!websocketKey || websocketKey.length !== 24) {
throw new Error('无效的 WebSocket Key');
}
// 3. 生成 Sec-WebSocket-Accept
const crypto = require('crypto');
const magicString = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const acceptKey = crypto
.createHash('sha1')
.update(websocketKey + magicString)
.digest('base64');
return acceptKey;
}
高级 WebSocket 实现
1. 带有重连和心跳的 WebSocket 客户端
javascript
class RobustWebSocket {
constructor(url, options = {}) {
this.url = url;
this.options = {
reconnectInterval: 1000,
maxReconnectAttempts: 10,
heartbeatInterval: 30000,
messageQueueSize: 100,
protocols: [],
...options
};
this.ws = null;
this.reconnectAttempts = 0;
this.messageQueue = [];
this.heartbeatTimer = null;
this.reconnectTimer = null;
this.isConnected = false;
this.eventListeners = {
open: [],
message: [],
error: [],
close: []
};
this.connect();
}
connect() {
try {
console.log(`连接 WebSocket: ${this.url}`);
this.ws = new WebSocket(this.url, this.options.protocols);
this.ws.onopen = (event) => {
console.log('WebSocket 连接已建立');
this.isConnected = true;
this.reconnectAttempts = 0;
// 发送缓存的消息
this.flushMessageQueue();
// 启动心跳检测
this.startHeartbeat();
// 触发监听器
this.emit('open', event);
};
this.ws.onmessage = (event) => {
const message = this.parseMessage(event.data);
// 处理心跳响应
if (message.type === 'pong') {
console.log('收到心跳响应');
return;
}
this.emit('message', message);
};
this.ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
this.emit('error', error);
};
this.ws.onclose = (event) => {
console.log('WebSocket 连接关闭:', event.code, event.reason);
this.isConnected = false;
this.stopHeartbeat();
this.emit('close', event);
// 尝试重连
if (this.shouldReconnect(event.code)) {
this.scheduleReconnect();
}
};
} catch (error) {
console.error('创建 WebSocket 失败:', error);
this.scheduleReconnect();
}
}
send(data, priority = 'normal') {
const message = {
data: data,
timestamp: Date.now(),
priority: priority,
id: this.generateMessageId()
};
if (this.isConnected && this.ws.readyState === WebSocket.OPEN) {
try {
this.ws.send(JSON.stringify(message));
console.log('消息已发送:', message.id);
} catch (error) {
console.error('发送消息失败:', error);
this.queueMessage(message);
}
} else {
this.queueMessage(message);
}
}
startHeartbeat() {
this.stopHeartbeat();
this.heartbeatTimer = setInterval(() => {
if (this.isConnected) {
const pingMessage = {
type: 'ping',
timestamp: Date.now()
};
try {
this.ws.send(JSON.stringify(pingMessage));
console.log('发送心跳包');
} catch (error) {
console.error('发送心跳包失败:', error);
}
}
}, this.options.heartbeatInterval);
}
stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
}
scheduleReconnect() {
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
console.log('达到最大重连次数,停止重连');
return;
}
this.reconnectAttempts++;
console.log(`尝试重连,第 ${this.reconnectAttempts} 次`);
this.reconnectTimer = setTimeout(() => {
this.connect();
}, this.options.reconnectInterval);
}
shouldReconnect(code) {
// 1000: 正常关闭
// 1001: 去往另一个服务器
// 1002: 协议错误
// 1003: 无法接受的数据
// 1005: 未设置状态码
// 1006: 关闭连接异常
// 1007: 不支持的数据类型
// 1008: 违反策略
// 1009: 消息过大
// 1010: 不支持的扩展
// 1011: 服务器错误
// 1012: 服务重启
// 1013: 临时重定向
// 1014: 无法接受的数据类型
// 1015: TLS握手失败
// 通常情况下,除了正常关闭(1000)外,都应该尝试重连
return code !== 1000;
}
parseMessage(data) {
try {
return JSON.parse(data);
} catch (error) {
console.error('解析消息失败:', error);
return null;
}
}
queueMessage(message) {
if (this.messageQueue.length >= this.options.messageQueueSize) {
console.log('消息队列已满,丢弃消息:', message.id);
return;
}
this.messageQueue.push(message);
console.log('消息已加入队列:', message.id);
}
flushMessageQueue() {
if (this.messageQueue.length === 0) return;
this.messageQueue.forEach(message => {
this.send(message.data, message.priority);
});
this.messageQueue = [];
}
generateMessageId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
}
on(event, listener) {
if (this.eventListeners[event]) {
this.eventListeners[event].push(listener);
}
}
emit(event, data) {
if (this.eventListeners[event]) {
this.eventListeners[event].forEach(listener => listener(data));
}
}
}
2. WebSocket 性能优化策略
消息压缩与批处理:
javascript
class OptimizedWebSocket extends RobustWebSocket {
constructor(url, options = {}) {
super(url, options);
this.messageBatch = [];
this.batchTimer = null;
this.compressionEnabled = options.compression || false;
}
// 批量发送消息以减少网络开销
batchSend(messages) {
this.messageBatch.push(...messages);
if (!this.batchTimer) {
this.batchTimer = setTimeout(() => {
this.flushBatch();
}, 50); // 50ms 批处理窗口
}
}
flushBatch() {
if (this.messageBatch.length === 0) return;
const batchMessage = {
type: 'batch',
messages: this.messageBatch,
compressed: this.compressionEnabled
};
let payload = JSON.stringify(batchMessage);
// 启用压缩
if (this.compressionEnabled && payload.length > 1024) {
payload = this.compress(payload);
}
super.send(payload);
this.messageBatch = [];
this.batchTimer = null;
}
compress(data) {
// 使用 Compression Streams API(如果支持)
if ('CompressionStream' in window) {
const stream = new CompressionStream('gzip');
// 实现压缩逻辑
return data; // 简化示例
}
return data;
}
}
WebSocket 与传统轮询对比
性能对比分析:
diff
短轮询 (Short Polling):
- 客户端定期发送HTTP请求
- 服务器立即响应(有无数据都响应)
- 网络开销:高(每次都有HTTP头)
- 实时性:差(取决于轮询间隔)
- 服务器负载:高
长轮询 (Long Polling):
- 客户端发送请求,服务器保持连接
- 有数据时才响应,无数据时超时
- 网络开销:中等
- 实时性:较好
- 服务器负载:中等(需要保持连接)
WebSocket:
- 一次握手建立持久连接
- 双向实时通信
- 网络开销:最低(只有数据帧)
- 实时性:最好
- 服务器负载:最低(复用连接)
高级网络性能优化技术
资源加载优化
1. 资源提示和预加载
html
<!-- 预连接:提前建立TCP/TLS连接 -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preconnect" href="https://api.example.com">
<!-- DNS预解析:提前进行DNS查询 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="dns-prefetch" href="//analytics.google.com">
<!-- 资源预加载:高优先级下载关键资源 -->
<link rel="preload" href="/css/critical.css" as="style">
<link rel="preload" href="/js/app.js" as="script">
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/images/hero.webp" as="image">
<!-- 页面预获取:在用户可能访问前预加载 -->
<link rel="prefetch" href="/page2.html">
<link rel="prefetch" href="/api/data.json">
<!-- 模块预加载:ES6模块预加载 -->
<link rel="modulepreload" href="/js/module.js">
2. 智能资源加载策略
javascript
// 自适应资源加载管理器
class AdaptiveResourceLoader {
constructor() {
this.connectionQuality = this.detectConnectionQuality();
this.deviceMemory = navigator.deviceMemory || 4;
this.hardwareConcurrency = navigator.hardwareConcurrency || 4;
}
detectConnectionQuality() {
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (!connection) return 'unknown';
const effectiveType = connection.effectiveType;
const downlink = connection.downlink;
const rtt = connection.rtt;
if (effectiveType === '4g' && downlink > 10) {
return 'fast';
} else if (effectiveType === '3g' || downlink > 1.5) {
return 'medium';
} else {
return 'slow';
}
}
async loadResources() {
const strategy = this.getLoadingStrategy();
switch (strategy) {
case 'aggressive':
await this.aggressiveLoading();
break;
case 'balanced':
await this.balancedLoading();
break;
case 'conservative':
await this.conservativeLoading();
break;
}
}
getLoadingStrategy() {
if (this.connectionQuality === 'fast' && this.deviceMemory >= 8) {
return 'aggressive';
} else if (this.connectionQuality === 'medium' || this.deviceMemory >= 4) {
return 'balanced';
} else {
return 'conservative';
}
}
async aggressiveLoading() {
// 高速网络 + 高性能设备:立即加载所有资源
const resources = [
'/js/app.js',
'/css/style.css',
'/images/hero.webp',
'/api/initial-data.json'
];
await Promise.all(resources.map(url => this.preloadResource(url)));
console.log('激进加载策略:所有资源已预加载');
}
async balancedLoading() {
// 中等网络:优先加载关键资源
const criticalResources = ['/css/critical.css', '/js/core.js'];
const nonCriticalResources = ['/js/analytics.js', '/css/animations.css'];
await Promise.all(criticalResources.map(url => this.preloadResource(url)));
// 延迟加载非关键资源
setTimeout(() => {
nonCriticalResources.forEach(url => this.preloadResource(url));
}, 100);
console.log('均衡加载策略:关键资源优先');
}
async conservativeLoading() {
// 慢速网络:只加载必要资源
const essentialResources = ['/css/minimal.css'];
await Promise.all(essentialResources.map(url => this.preloadResource(url)));
// 懒加载其他资源
this.setupLazyLoading();
console.log('保守加载策略:最小化资源加载');
}
preloadResource(url) {
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'preload';
link.href = url;
link.as = this.getResourceType(url);
link.onload = resolve;
link.onerror = reject;
document.head.appendChild(link);
});
}
getResourceType(url) {
if (url.endsWith('.css')) return 'style';
if (url.endsWith('.js')) return 'script';
if (url.match(/\.(jpg|jpeg|png|webp|svg)$/)) return 'image';
if (url.match(/\.(woff|woff2|ttf|otf)$/)) return 'font';
return 'fetch';
}
}
3. 图片加载优化
javascript
// 现代图片加载系统
class ModernImageLoader {
constructor() {
this.intersectionObserver = this.createIntersectionObserver();
this.supportedFormats = this.detectSupportedFormats();
}
detectSupportedFormats() {
const canvas = document.createElement('canvas');
const formats = {
webp: canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0,
avif: canvas.toDataURL('image/avif').indexOf('data:image/avif') === 0,
jxl: false // JPEG XL 支持检测
};
return formats;
}
createIntersectionObserver() {
return new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadImage(entry.target);
this.intersectionObserver.unobserve(entry.target);
}
});
}, {
rootMargin: '50px', // 提前50px开始加载
threshold: 0.1
});
}
setupLazyImages() {
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => {
this.intersectionObserver.observe(img);
});
}
loadImage(img) {
const baseUrl = img.dataset.src;
const sizes = img.dataset.sizes || '100vw';
// 生成响应式图片URL
const srcset = this.generateResponsiveSrcset(baseUrl, sizes);
// 创建新图片元素用于预加载
const newImg = new Image();
newImg.onload = () => {
// 图片加载完成,更新属性
img.src = newImg.src;
img.srcset = newImg.srcset;
img.classList.add('loaded');
// 添加淡入动画
img.style.opacity = '0';
img.style.transition = 'opacity 0.3s';
requestAnimationFrame(() => {
img.style.opacity = '1';
});
};
newImg.onerror = () => {
// 图片加载失败,显示占位图
img.src = this.generatePlaceholder(img.clientWidth, img.clientHeight);
img.classList.add('error');
};
newImg.srcset = srcset;
newImg.sizes = sizes;
}
generateResponsiveSrcset(baseUrl, sizes) {
const breakpoints = [320, 480, 768, 1024, 1280, 1920];
const format = this.getBestFormat();
return breakpoints.map(width => {
const url = this.buildImageUrl(baseUrl, width, format);
return `${url} ${width}w`;
}).join(', ');
}
getBestFormat() {
if (this.supportedFormats.avif) return 'avif';
if (this.supportedFormats.webp) return 'webp';
return 'jpg';
}
buildImageUrl(baseUrl, width, format) {
// 根据图片服务构建 URL(例如 Cloudinary、ImageKit 等)
return `${baseUrl}?w=${width}&f=${format}&q=auto`;
}
generatePlaceholder(width, height) {
// SVG 占位图
const svg = `
<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="#f0f0f0"/>
<text x="50%" y="50%" text-anchor="middle" dy="0.3em" fill="#999">
图片加载失败
</text>
</svg>
`;
return `data:image/svg+xml;base64,${btoa(svg)}`;
}
}
// 使用示例
const imageLoader = new ModernImageLoader();
Document.addEventListener('DOMContentLoaded', () => {
imageLoader.setupLazyImages();
});
网络请求优化
1. HTTP/2 服务器推送优化
javascript
// Node.js HTTP/2 服务器端实现
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
class HTTP2Server {
constructor() {
this.server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
});
this.setupPushStrategy();
}
setupPushStrategy() {
this.server.on('stream', (stream, headers) => {
const method = headers[':method'];
const path = headers[':path'];
if (method === 'GET' && path === '/') {
this.handleIndexRequest(stream, headers);
}
});
}
handleIndexRequest(stream, headers) {
// 预测用户需要的资源
const criticalResources = [
{ path: '/css/critical.css', type: 'text/css' },
{ path: '/js/app.js', type: 'application/javascript' },
{ path: '/fonts/main.woff2', type: 'font/woff2' }
];
// 执行服务器推送
criticalResources.forEach(resource => {
this.pushResource(stream, resource);
});
// 返回HTML
const html = this.generateHTML();
stream.respond({
':status': 200,
'content-type': 'text/html; charset=utf-8',
'cache-control': 'public, max-age=3600'
});
stream.end(html);
}
pushResource(stream, resource) {
try {
// 检查客户端是否已缓存
if (this.shouldPush(resource.path)) {
stream.pushStream({ ':path': resource.path }, (err, pushStream) => {
if (err) {
console.error('服务器推送失败:', err);
return;
}
const fileContent = fs.readFileSync(path.join(__dirname, 'public', resource.path));
pushStream.respond({
':status': 200,
'content-type': resource.type,
'cache-control': 'public, max-age=86400'
});
pushStream.end(fileContent);
console.log(`推送资源: ${resource.path}`);
});
}
} catch (error) {
console.error('推送资源失败:', error);
}
}
shouldPush(resourcePath) {
// 简化的推送策略:检查是否为首次访问
// 实际中应该根据 Cookie、Referer 等信息判断
return true;
}
generateHTML() {
return `
<!DOCTYPE html>
<html>
<head>
<title>高性能网站</title>
<link rel="stylesheet" href="/css/critical.css">
</head>
<body>
<h1>欢迎来到高性能网站</h1>
<script src="/js/app.js"></script>
</body>
</html>
`;
}
}
2. 请求合并与批处理
javascript
// 智能请求合并系统
class RequestBatcher {
constructor() {
this.batches = new Map();
this.timeouts = new Map();
this.batchDelay = 10; // 10ms 合并窗口
}
// 自动合并相似的API请求
async request(url, options = {}) {
const batchKey = this.getBatchKey(url, options);
if (!this.batches.has(batchKey)) {
this.batches.set(batchKey, []);
}
return new Promise((resolve, reject) => {
const batch = this.batches.get(batchKey);
batch.push({ url, options, resolve, reject });
// 设置批处理定时器
if (!this.timeouts.has(batchKey)) {
const timeoutId = setTimeout(() => {
this.executeBatch(batchKey);
}, this.batchDelay);
this.timeouts.set(batchKey, timeoutId);
}
});
}
getBatchKey(url, options) {
// 根据URL和请求参数生成批处理键
const baseUrl = url.split('?')[0];
const method = options.method || 'GET';
return `${method}:${baseUrl}`;
}
async executeBatch(batchKey) {
const batch = this.batches.get(batchKey);
if (!batch || batch.length === 0) return;
// 清理定时器和批处理
clearTimeout(this.timeouts.get(batchKey));
this.timeouts.delete(batchKey);
this.batches.delete(batchKey);
try {
if (batch.length === 1) {
// 单个请求直接执行
const { url, options, resolve, reject } = batch[0];
const response = await fetch(url, options);
resolve(response);
} else {
// 多个请求合并执行
await this.executeBatchedRequests(batch);
}
} catch (error) {
// 批处理失败,通知所有请求
batch.forEach(({ reject }) => reject(error));
}
}
async executeBatchedRequests(batch) {
// 构建批处理请求
const batchRequest = {
requests: batch.map(({ url, options }, index) => ({
id: index,
url: url,
method: options.method || 'GET',
headers: options.headers || {},
body: options.body
}))
};
// 发送批处理请求到服务器
const response = await fetch('/api/batch', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(batchRequest)
});
const batchResponse = await response.json();
// 分发响应结果
batchResponse.responses.forEach((res, index) => {
const { resolve, reject } = batch[index];
if (res.status >= 200 && res.status < 300) {
resolve({
ok: true,
status: res.status,
json: () => Promise.resolve(res.body),
text: () => Promise.resolve(JSON.stringify(res.body))
});
} else {
reject(new Error(`Request failed with status ${res.status}`));
}
});
}
}
// 使用示例
const batcher = new RequestBatcher();
// 这些请求将被自动合并
async function loadUserData() {
const [profile, settings, notifications] = await Promise.all([
batcher.request('/api/user/profile'),
batcher.request('/api/user/settings'),
batcher.request('/api/user/notifications')
]);
console.log('用户数据加载完成');
}
传输优化
1. 压缩算法对比:
makefile
Gzip: 压缩率70-80%,CPU消耗中等,兼容性最好
Brotli: 压缩率75-85%,CPU消耗较高,现代浏览器支持
Deflate: 压缩率65-75%,CPU消耗较低,较少使用
网络安全与防护
常见攻击与防护
1. XSS防护:
http
# Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
# XSS Protection
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
2. CSRF防护:
javascript
// CSRF Token验证
app.use((req, res, next) => {
if (['POST', 'PUT', 'DELETE'].includes(req.method)) {
const token = req.headers['x-csrf-token'] || req.body._token;
if (!validateCSRFToken(token, req.session)) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
}
next();
});
总结: 前端网络知识涵盖了从URL输入到页面展示的完整流程,包括DNS解析、TCP连接、HTTP协议、缓存机制、CDN分发等核心技术。理解这些底层原理对于前端性能优化和问题排查至关重要。现代Web开发中,HTTP/2、HTTP/3、Service Worker等新技术正在革命性地改善用户体验。
Service Worker 缓存策略深度解析
Service Worker 生命周期
javascript
// Service Worker 安装和激活
self.addEventListener('install', event => {
console.log('Service Worker 安装中...');
// 预缓存关键资源
event.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll([
'/',
'/css/critical.css',
'/js/app.js',
'/offline.html'
]);
})
);
// 强制跳过等待
self.skipWaiting();
});
self.addEventListener('activate', event => {
console.log('Service Worker 已激活');
// 清理旧缓存
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== 'v1') {
return caches.delete(cacheName);
}
})
);
})
);
// 立即控制所有页面
return self.clients.claim();
});
高级缓存策略实现
javascript
// 多重缓存策略
class CacheStrategyManager {
constructor() {
this.strategies = {
'cache-first': this.cacheFirst.bind(this),
'network-first': this.networkFirst.bind(this),
'stale-while-revalidate': this.staleWhileRevalidate.bind(this),
'network-only': this.networkOnly.bind(this),
'cache-only': this.cacheOnly.bind(this)
};
}
// 缓存优先策略
async cacheFirst(request, cacheName) {
const cache = await caches.open(cacheName);
const cachedResponse = await cache.match(request);
if (cachedResponse) {
return cachedResponse;
}
try {
const networkResponse = await fetch(request);
if (networkResponse.ok) {
cache.put(request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
console.error('网络请求失败:', error);
return new Response('离线模式', { status: 503 });
}
}
// 网络优先策略
async networkFirst(request, cacheName, timeout = 3000) {
const cache = await caches.open(cacheName);
try {
const networkResponse = await Promise.race([
fetch(request),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('网络超时')), timeout)
)
]);
if (networkResponse.ok) {
cache.put(request, networkResponse.clone());
}
return networkResponse;
} catch (error) {
console.log('网络失败,使用缓存:', error.message);
const cachedResponse = await cache.match(request);
return cachedResponse || new Response('资源不可用', { status: 404 });
}
}
// 过期时重新验证策略
async staleWhileRevalidate(request, cacheName, maxAge = 86400000) {
const cache = await caches.open(cacheName);
const cachedResponse = await cache.match(request);
// 后台更新
const fetchPromise = fetch(request).then(response => {
if (response.ok) {
cache.put(request, response.clone());
}
return response;
});
if (cachedResponse) {
const responseTime = new Date(cachedResponse.headers.get('date')).getTime();
const isStale = (Date.now() - responseTime) > maxAge;
if (isStale) {
return fetchPromise;
} else {
fetchPromise.catch(() => {}); // 静默更新
return cachedResponse;
}
}
return fetchPromise;
}
}
最终总结: 通过深入理解浏览器URL输入到页面展示的完整网络流程,包括DNS解析、TCP/UDP协议、HTTP协议演进、缓存机制、WebSocket实时通信、以及现代网络安全防护,前端开发者能够构建更高性能、更安全的Web应用。这些知识不仅有助于日常开发工作,也是技术面试和解决复杂网络问题的关键基础。