面试知识库

TCP 三次握手 → Socket → Netty 追问链#

追问路径#

涉及知识点#

核心串联逻辑#

  1. TCP握手建立可靠连接后,服务端accept()返回Socket
  2. BIO → NIO:BIO一连接一线程,上万连接时线程内存和上下文切换开销都很大(1MB栈只是虚拟地址预留);NIO通过Selector一线程管多连接
  3. epoll优势:O(1)事件通知(vs select O(n)),无fd数量限制(vs select 1024),ET模式减少事件触发次数
  4. Netty封装:解决JDK NIO的epoll空轮询bug,提供主从Reactor线程模型,池化内存管理
  5. 堆外内存:DirectByteBuffer绕过JVM堆,Socket读写少一次从堆到native的memcpy
  6. 代码示例:
    // Netty主从Reactor典型配置
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);     // accept线程(4.2起此类废弃,改用MultiThreadIoEventLoopGroup+NioIoHandler.newFactory())
    EventLoopGroup workerGroup = new NioEventLoopGroup();     // 默认CPU*2
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
     .channel(NioServerSocketChannel.class)
     .childHandler(new ChannelInitializer<>() { /* Pipeline配置 */ });
    java

面试回答串联#

30秒速答#

TCP三次握手建连后,BIO每连接一线程上限约1万。NIO通过Selector多路复用让单线程管多连接。Linux上epoll用红黑树+就绪链表实现O(1)事件通知。生产用Netty的主从Reactor——BossGroup负责accept,WorkerGroup负责IO读写。

2分钟展开答#

TCP三次握手确认双方收发能力后建立连接。传统BIO模型每个连接一个线程阻塞读写,线程栈预留约1MB虚拟地址(实际占用几十到几百KB),上万连接时内存和上下文切换开销都很大。NIO通过Selector多路复用让一个线程监听多个Channel的IO事件。Linux上epoll用红黑树管理fd+就绪链表存储就绪事件,事件通知是O(1)而select是O(n),也没有1024的fd数量限制。epoll有LT(水平触发)和ET(边缘触发)两种模式,Netty默认的NIO传输走JDK Selector,是LT;原生epoll传输在4.1默认ET,4.2起固定用LT。为什么不直接用Java NIO?因为JDK的Selector有epoll空轮询bug会导致CPU 100%,Netty自动检测并重建Selector解决了这个问题。Netty的线程模型是主从Reactor——BossGroup 1-2个线程负责accept新连接,WorkerGroup默认CPU核数×2个线程处理IO读写,Handler链式处理业务。内存管理上Netty用PooledByteBufAllocator池化+堆外内存(DirectByteBuffer),省掉一次从JVM堆到native内存的memcpy。

相关追问链#