Generated comprehensive interview preparation materials covering: - Distributed systems (transactions, locks, ID generation, consistency) - Database (indexing, sharding, replication, transactions) - Caching (Redis, cache problems, distributed lock) - Message queues (RocketMQ, Kafka) - Concurrency (ThreadLocal, ConcurrentHashMap, thread pools) - JVM (GC, memory, tuning) - System design (seckill, short URL, IM, feed, LBS) - Algorithms (B+ tree, LRU, Red-Black tree, Skip list, Timing wheel) - Network (TCP/IP, HTTP/HTTPS) - Security (encryption, SQL injection, XSS) - Performance tuning - Design patterns - Microservices (Spring Boot, Gateway, Service Mesh) - Container orchestration (Kubernetes, Docker) - CI/CD, observability Each file includes: - Detailed questions - Comprehensive answers - Code examples - Real project experience - Alibaba P7 level requirements Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
15 KiB
15 KiB
TCP/IP 网络协议
问题
- TCP 和 UDP 的区别是什么?
- TCP 三次握手和四次挥手的流程是什么?为什么需要三次握手?
- TCP 如何保证可靠传输?
- 什么是 SYN 洪水攻击?如何防范?
- HTTP 和 HTTPS 的区别是什么?
- HTTP 1.1、2.0、3.0 的演进历程和主要特性
- 什么是粘包和拆包?如何解决?
- 在实际项目中遇到过哪些网络问题?
标准答案
1. TCP vs UDP
对比表
| 特性 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接 | 无连接 |
| 可靠性 | 可靠传输 | 不可靠 |
| 顺序 | 保证顺序 | 不保证顺序 |
| 速度 | 较慢 | 快 |
| 流量控制 | 有(滑动窗口) | 无 |
| 拥塞控制 | 有 | 无 |
| 首部开销 | 20-60 字节 | 8 字节 |
| 应用场景 | 文件传输、邮件、HTTP | 视频流、直播、DNS |
TCP 特性
面向连接:
客户端 服务器
│ │
│─────── SYN ───────────────→│ 建立连接
│←────── SYN+ACK ────────────│
│─────── ACK ───────────────→│
│ │
│─────── 数据 ───────────────→│
│←─────── ACK ───────────────│
│ │
│─────── FIN ───────────────→│ 断开连接
│←─────── ACK ───────────────│
│←────── FIN ────────────────│
│─────── ACK ───────────────→│
可靠传输:
- 确认应答(ACK)
- 超时重传
- 校验和
- 序列号
流量控制:
- 滑动窗口协议
- 动态调整窗口大小
UDP 特性
无连接、不可靠:
客户端 服务器
│ │
│─────── 数据报 ─────────────→│ (可能丢失)
│─────── 数据报 ─────────────→│ (可能乱序)
│ │
│ │
优点:
- 速度快(无连接、无确认)
- 开销小(首部 8 字节)
- 支持一对一、一对多、多对多
应用场景:
- 视频直播(可容忍丢帧)
- 在线游戏(实时性要求高)
- DNS 查询(请求响应快)
- VoIP(语音通话)
2. TCP 三次握手和四次挥手
三次握手
流程:
客户端 服务器
│ │
│─────── SYN=1, seq=x ──────→│ SYN_SENT
│ │
│←───── SYN=1, ACK=1, seq=y, ack=x+1 ───│
│ SYN_RCVD │
│ │
│─────── ACK=1, seq=x+1, ack=y+1 ────→│ ESTABLISHED
│ ESTABLISHED │
状态变化:
客户端:CLOSED → SYN_SENT → ESTABLISHED
服务器:CLOSED → LISTEN → SYN_RCVD → ESTABLISHED
为什么需要三次握手?
目的:
-
确认双方收发能力:
- 第一次握手:服务端确认客户端能发
- 第二次握手:客户端确认服务端能收能发
- 第三次握手:服务端确认客户端能收
-
防止已失效的连接请求突然又传送到服务端:
场景:客户端发送的第一个连接请求在网络中滞留 结果:客户端超时重发,建立连接后,滞留的请求到达 如果只有两次握手: ─ 客户端发送 SYN ─ 服务器收到,建立连接,等待数据 ─ 滞留的 SYN 到达,服务器又建立连接(错误!) 三次握手避免: ─ 服务器收到滞留的 SYN,回复 SYN+ACK ─ 客户端发现 ack 不对,丢弃(不建立连接) -
同步初始序列号(ISN):
- 双方协商好初始序列号
- 保证数据的顺序和去重
四次挥手
流程:
客户端 服务器
│ │
│─────── FIN=1, seq=u ──────→│ FIN_WAIT1
│ │ CLOSE_WAIT
│←─────── ACK=1, seq=v, ack=u+1 ───│
│ FIN_WAIT2 │
│ │
│←─────── FIN=1, ACK=1, seq=w, ack=u+1 ───│
│ TIME_WAIT │ LAST_ACK
│ │
│─────── ACK=1, seq=u+1, ack=w+1 ────→│ CLOSED
│ (等待 2MSL) │
状态变化:
客户端:ESTABLISHED → FIN_WAIT1 → FIN_WAIT2 → TIME_WAIT → CLOSED
服务器:ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
为什么需要四次挥手?
原因:
- TCP 是全双工协议(双向传输)
- 双方都需要关闭发送方向
流程:
- 客户端发送 FIN(关闭客户端→服务器方向)
- 服务器确认 ACK(但服务器可能还有数据要发送)
- 服务器发送 FIN(关闭服务器→客户端方向)
- 客户端确认 ACK
为什么 TIME_WAIT 状态需要等待 2MSL?
MSL(Maximum Segment Lifetime):
- 报文最大生存时间(通常 30 秒 - 2 分钟)
- 2MSL = 1 分钟 - 4 分钟
目的:
-
确保最后一个 ACK 能到达:
- 如果 ACK 丢失,服务器会重传 FIN
- 客户端等待 2MSL,可以重传 ACK
-
让旧连接的报文自然消失:
- 防止旧连接的报文干扰新连接
- 确保网络中所有旧报文都已消失
问题:
- 大量 TIME_WAIT 会导致端口资源耗尽
- 解决:调低
TIME_WAIT时间或端口复用
# Linux 调整
net.ipv4.tcp_tw_reuse = 1 # 端口复用
net.ipv4.tcp_tw_recycle = 0 # 关闭快速回收(有坑)
3. TCP 可靠传输机制
核心机制
-
序列号(Sequence Number):
- 每个字节都有编号
- 用于排序和去重
-
确认应答(ACK):
- 接收方确认收到的数据
- ACK = 下一个期望接收的字节序号
发送方:seq=1000, len=100
接收方:ack=1100(期待下一个字节)
-
超时重传(RTO):
- 发送方启动定时器
- 超时未收到 ACK,重传数据
-
快速重传:
- 收到 3 个重复 ACK,立即重传
- 无需等待超时
发送方:seq=1000, len=100
接收方:期望 1100,但收到 1200(乱序)
接收方:连续发送 ack=1100(3 次)
发送方:收到 3 个重复 ack,快速重传
-
滑动窗口:
- 流量控制
- 动态调整发送速率
-
拥塞控制:
- 慢启动、拥塞避免、快重传、快恢复
4. SYN 洪水攻击
攻击原理
场景:攻击者发送大量 SYN 包,但不完成三次握手。
攻击者 服务器
│ │
├─── SYN ─────────────────────→│ 分配资源
├─── SYN ─────────────────────→│ 分配资源
├─── SYN ─────────────────────→│ 分配资源
├─── SYN ─────────────────────→│ 分配资源
│ (不回复 ACK) │ 资源耗尽
│ │ 无法服务正常用户
后果:
- 服务器维护大量
SYN_RCVD连接 - 内存资源耗尽
- 无法响应正常用户的连接请求
防范措施
1. SYN Cookies:
# 开启 SYN Cookies
net.ipv4.tcp_syncookies = 1
原理:
- 不分配资源
- 计算 Cookie 并编码在 SYN+ACK 的初始序列号中
- 客户端回复 ACK 时验证 Cookie
2. 增加 SYN 队列:
net.ipv4.tcp_max_syn_backlog = 8192
3. 缩短超时时间:
net.ipv4.tcp_synack_retries = 2
4. 防火墙:
- 限制单个 IP 的连接数
- 检测异常流量并拦截
5. HTTP vs HTTPS
对比
| 特性 | HTTP | HTTPS |
|---|---|---|
| 协议 | 应用层 | 应用层 + 安全层(SSL/TLS) |
| 端口 | 80 | 443 |
| 加密 | 明文传输 | 加密传输 |
| 证书 | 不需要 | 需要 CA 证书 |
| 性能 | 快 | 较慢(TLS 握手) |
| SEO | 无优惠 | 搜索引擎优先排名 |
HTTPS 工作流程
客户端 服务器
│ │
│─────── ClientHello ────────────→│ (支持的加密套件)
│ │
│←────── ServerHello ─────────────│ (选择的加密套件 + 证书)
│←────── Certificate ─────────────│
│ │
│─────── ClientKeyExchange ─────→│ (生成随机数)
│─────── ChangeCipherSpec ───────→│ (之后消息加密)
│─────── Finished ───────────────→│
│ │
│←────── ChangeCipherSpec ────────│
│←────── Finished ────────────────│
│ │
│══════ 加密通信 ══════════════════│
HTTPS 的安全性
- 数据加密:防止中间人窃听
- 数据完整性:防止数据被篡改
- 身份认证:防止钓鱼网站
6. HTTP 版本演进
HTTP/1.0
特点:
- 每个请求都需要新的 TCP 连接
- 无状态、无连接
问题:
- 性能差(频繁建立连接)
- 队头阻塞
HTTP/1.1
改进:
- 持久连接:
Connection: keep-alive - 管道化(Pipelining):可发送多个请求
- 分块传输:
Transfer-Encoding: chunked - 缓存:更强的缓存控制
问题:
- 队头阻塞仍然存在
- 请求串行执行
HTTP/2.0
改进:
- 二进制协议:不再是纯文本
- 多路复用:一个 TCP 连接并发多个请求
- 头部压缩:HPACK 算法
- 服务端推送:Server Push
多路复用:
HTTP/1.1:
请求1 → ━━━ 连接1 ━━━ → 响应1
请求2 → ━━━ 连接2 ━━━ → 响应2
请求3 → ━━━ 连接3 ━━━ → 响应3
HTTP/2.0:
请求1 ┓
请求2 ┣━━━━ 单连接 ━━━→ ┳ 响应1
请求3 ┛ ┻ 响应2
响应3
HTTP/3.0(QUIC)
改进:
- 基于 UDP:不再是 TCP
- 解决队头阻塞:流级别隔离
- 更快握手:0-RTT
- 连接迁移:IP 变化不影响连接
架构:
HTTP/3.0
↓
QUIC(UDP)
↓
加密、可靠传输、流控制
7. 粘包和拆包
问题
TCP 是字节流协议,无消息边界:
发送方发送两个包:
┌──────┐ ┌──────┐
│ 包1 │ │ 包2 │
└──────┘ └──────┘
接收方可能收到:
1. 正常:┌──────┐┌──────┐
2. 粘包:┌──────┐┌──────┐(两个包粘在一起)
3. 拆包:┌────┐ ┌──┐┌──┐┌────┐(包被拆散)
解决方案
1. 固定长度:
每个包固定 100 字节
优点:简单
缺点:浪费空间(短消息)
2. 分隔符:
每个包以 \n 结束
优点:实现简单
缺点:内容中不能有分隔符
3. 长度字段(推荐):
┌────┬──────────┐
│长度│ 数据 │
└────┴──────────┘
实现:Netty 的 LengthFieldBasedFrameDecoder
Netty 示例:
// 服务端
public class Server {
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
// 解决粘包拆包:长度字段解码器
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
1024 * 1024, // 最大帧长度
4, // 长度字段偏移量
4, // 长度字段长度
0, // 长度调整值
4 // 剥离的字节数
));
ch.pipeline().addLast(new MessageHandler());
}
});
bootstrap.bind(8080).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
// 消息编解码
public class MessageEncoder extends MessageToByteEncoder<Message> {
@Override
protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) {
byte[] data = msg.getBody().getBytes();
out.writeInt(data.length); // 长度字段
out.writeBytes(data); // 数据字段
}
}
8. 实际项目经验
案例 1:TCP 长连接异常断开
问题:
- 客户端崩溃,服务器未收到 FIN
- 服务器维护大量死连接
解决:
// 启用 TCP Keep-Alive
socket.setKeepAlive(true);
// 应用层心跳
@Scheduled(fixedRate = 30000)
public void sendHeartbeat() {
channel.writeAndFlush(new HeartbeatMessage());
}
// 超时断开
ch.pipeline().addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS));
ch.pipeline().addLast(new HeartbeatHandler());
案例 2:HTTPS 性能优化
问题:
- HTTPS 握手耗时 200ms+
- 高并发下性能差
解决:
- HTTP/2 多路复用
- TLS False Start:减少 1 个 RTT
- Session Resumption:恢复会话
- HSTS:强制 HTTPS,避免重定向
9. 阿里 P7 加分项
深度理解:
- 理解 TCP 的拥塞控制算法( Reno、Cubic、BBR)
- 理解 QUIC 协议的设计原理
- 理解 TLS 1.3 的改进(0-RTT、加密握手)
实战经验:
- 有处理网络抖动导致的连接不稳定问题
- 有 TCP 参数调优经验
- 有 HTTPS 性能优化经验
架构能力:
- 能设计高性能的网络通信框架
- 能设计跨地域的网络架构
- 有网络监控和故障排查经验
技术选型:
- 了解 gRPC、Thrift 等 RPC 框架
- 了解 Netty、Mina 等网络框架
- 能根据业务特点选择合适的协议