TCP 三次握手 → Socket → Netty 追问链#
追问路径#
Q: TCP三次握手过程?
→ 客户端SYN → 服务端SYN+ACK → 客户端ACK;三次是确认双方收发能力的最小次数
Q: 服务端accept之后连接怎么处理?
→ Socket编程:accept()返回已连接Socket,传统BIO模式一个连接分配一个线程处理
Q: BIO的问题是什么?
→ 线程资源耗尽:每个连接一个线程,1万连接需要1万线程(每个线程~1MB栈),上限约1万连接
├─ Q: NIO怎么解决的?
│ → Selector多路复用:一个线程监听多个Channel的IO事件(OP_ACCEPT/OP_READ/OP_WRITE)
│ Q: select/poll/epoll有什么区别?
│ → select(fd数组最大1024)/poll(链表无上限)/epoll(红黑树+就绪链表, O(1)事件通知)
│ Q: epoll的ET和LT模式?
│ → LT(水平触发, 只要有数据就通知)/ET(边缘触发, 状态变化才通知, 必须一次读完, 性能更高)
│ Q: Netty用的哪种?
│ → Linux上用epoll ET模式;Netty的EpollEventLoop直接用JNI调用epoll_wait
└─ Q: 生产环境为什么用Netty不直接用Java NIO?
→ Java NIO的Selector有epoll空轮询bug(CPU 100%);Netty自动检测并重建Selector
Q: Netty的线程模型?
→ 主从Reactor:BossGroup(1-2线程accept新连接) + WorkerGroup(CPU核数×2线程处理IO)
Q: Netty的内存管理有什么特点?
→ PooledByteBufAllocator池化 + 堆外内存(DirectByteBuffer, 减少一次用户态-内核态拷贝) + 引用计数释放plaintext涉及知识点#
- TCP三次握手与四次挥手 — 连接建立与断开
- TCP可靠传输机制 — 序号/确认/重传/滑动窗口
- TCP粘包与拆包 — Netty的LengthFieldBasedFrameDecoder
- BIO-NIO-AIO对比 — IO模型演进
- select-poll-epoll对比 — 多路复用实现差异
- epoll原理 — 红黑树+就绪链表+回调机制
- IO多路复用 — 一个线程处理多连接的核心思想
- Reactor模式 — 高性能网络编程的核心模式
- 零拷贝原理 — sendfile/mmap减少数据拷贝
- 用户态与内核态 — 系统调用与内存拷贝开销
核心串联逻辑#
- TCP握手建立可靠连接后,服务端accept()返回Socket
- BIO → NIO:BIO一连接一线程上限约1万(线程栈~1MB×10000=10GB);NIO通过Selector一线程管多连接
- epoll优势:O(1)事件通知(vs select O(n)),无fd数量限制(vs select 1024),ET模式减少事件触发次数
- Netty封装:解决JDK NIO的epoll空轮询bug,提供主从Reactor线程模型,池化内存管理
- 堆外内存:DirectByteBuffer绕过JVM堆,Socket读写少一次从堆到native的memcpy
- 代码示例:
java// Netty主从Reactor典型配置 EventLoopGroup bossGroup = new NioEventLoopGroup(1); // accept线程 EventLoopGroup workerGroup = new NioEventLoopGroup(); // 默认CPU*2 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<>() { /* Pipeline配置 */ });
面试回答串联#
30秒速答#
“TCP三次握手建连后,BIO每连接一线程上限约1万。NIO通过Selector多路复用让单线程管多连接。Linux上epoll用红黑树+就绪链表实现O(1)事件通知。生产用Netty的主从Reactor——BossGroup负责accept,WorkerGroup负责IO读写。“
2分钟展开答#
“TCP三次握手确认双方收发能力后建立连接。传统BIO模型每个连接一个线程阻塞读写,线程栈约1MB,1万连接就需要10GB内存,实际上限约1万连接。NIO通过Selector多路复用让一个线程监听多个Channel的IO事件。Linux上epoll用红黑树管理fd+就绪链表存储就绪事件,事件通知是O(1)而select是O(n),也没有1024的fd数量限制。epoll有LT(水平触发)和ET(边缘触发)两种模式,Netty在Linux上用ET模式性能更高。为什么不直接用Java NIO?因为JDK的Selector有epoll空轮询bug会导致CPU 100%,Netty自动检测并重建Selector解决了这个问题。Netty的线程模型是主从Reactor——BossGroup 1-2个线程负责accept新连接,WorkerGroup默认CPU核数×2个线程处理IO读写,Handler链式处理业务。内存管理上Netty用PooledByteBufAllocator池化+堆外内存(DirectByteBuffer),减少用户态到内核态的一次memcpy。“
相关追问链#
- MQ可靠性-顺序-积压-事务消息追问链 — Kafka/RocketMQ底层使用Netty做网络传输
- 进程线程-调度-上下文切换-协程追问链 — IO模型与线程调度的关系