从 TCP 到 IO 模型:为什么高并发不能只靠阻塞线程
后端基础

从 TCP 到 IO 模型:为什么高并发不能只靠阻塞线程

高并发问题很多时候不是 TCP 本身不行,而是传统阻塞 IO 的线程模型先撑不住。

本文整理自早期学习笔记,发布时间按学习阶段归档。

正文

线程通信:TCP 为例

图片占位:Pasted image 20260415213010.png

TCP 为什么不够好?(不考虑 tcp 未加密的情况)

[[RPC]]

TCP 的核心问题,本质是传统阻塞 IO(BIO) 模型的线程瓶颈

  • BIO 的工作模式:1 连接对应 1 线程
  • 高并发下的致命问题:线程资源耗尽、上下文切换开销爆炸、阻塞导致线程资源浪费

多线程通信

线程之间通信的方案选择
Hashmap——->currenthashmap
共享变量

BIO 到 NIO 的演变

NIO 的核心设计

Buffer/Channel/Selector
1 线程伺候 1 个连接」到「1 线程管理 N 个连接

图片占位:产出 2026-04-15 20.11.49.excalidraw

代码

不同平台的 NIO

Windows 中 NIO 的底层是:以 windows 举例

图片占位:产出 2026-04-15 20.07.43.excalidraw

  • 在Windows上(Java 8)会显示:sun.nio.ch.WindowsSelectorImpl
  • 在Windows上(Java 9+)会显示:sun.nio.ch.WEPollSelectorImpl
  • Windows Event
平台 1000 个连接 10000 个连接 适合场景
Linux (epoll) ✅ 轻松 ✅ 轻松 高并发服务器
Windows (select) ⚠️ 还行 ❌ 吃力 普通应用
Windows (Java 9+ WEPoll) ✅ 还行 ⚠️ 一般 中等并发

上一部分我们搞懂了 Java 原生 NIO 的原理,但原生 NIO 开发有大量坑(空轮询 Bug、拆包粘包、异常处理复杂),工业界几乎不会直接使用原生 NIO,而 Netty 就是 NIO 的标准化、高性能封装

NIO 的实现 netty

~~具体的 servers 创建的代码:借鉴于反射的 hander 代理对象:~~封装的思想

  • 动态代理:Proxy.newProxyInstance 搭台
  • Netty:启动器 搭台
  • 具体干活的逻辑,全部抽出来,封装进一个「Handler」里

动态代理:逻辑写在 handler.invoke()
Netty:逻辑写在 MyHandler.channelRead()

// 3. 配置核心参数
bootstrap.group(bossGroup, workerGroup) // 绑定主从线程组
         .channel(NioServerSocketChannel.class) // 指定NIO通道类型
         .option(ChannelOption.SO_BACKLOG, 128) // 连接队列大小
         .childOption(ChannelOption.SO_KEEPALIVE, true) // 心跳保活
         // 4. 初始化管道,添加自定义处理器
         .childHandler(new ChannelInitializer<SocketChannel>() {
             @Override
             protected void initChannel(SocketChannel ch) {
                 // 向Pipeline添加自定义Handler(业务逻辑)
                 ch.pipeline().addLast(new MyServerHandler());
             }
         });
//反射的代理类
// 动态代理演示。  
        // 创建动态代理调用处理器。  
        SetterLoggingInvocationHandler handler = new SetterLoggingInvocationHandler(realPerson);  
        // 基于 PersonApi 接口创建动态代理对象。  
        PersonApi dynamicProxy = (PersonApi) Proxy.newProxyInstance(  
                PersonApi.class.getClassLoader(),  
                new Class<?>[]{PersonApi.class},  
                handler  
        );

主从 Reactor 线程模型、零拷贝、内存池

引入虚拟线程
代码

对比

图片占位:产出 2026-04-21 20.08.08.excalidraw

主流 RPC 框架的 NIO 实现

  • Dubbo:默认使用Netty作为底层通信框架,基于 NIO 实现 TCP 长连接通信,采用 Reactor 主从多线程模型:
  • BossGroup:主 Reactor 线程组,负责处理 TCP 连接请求
  • WorkerGroup:从 Reactor 线程组,负责处理已建立连接的 IO 读写事件
  • gRPC:基于 HTTP/2 协议,底层使用Netty或OkHttp实现,同样采用 NIO 模型,支持多路复用和头部压缩。
  • SOFARPC:蚂蚁集团开源框架,完全基于 Netty构建,通过封装 TCP 长连接实现高性能远程调用。
  • Hadoop RPC:直接基于Java NIO实现,使用 Protocol Buffers 进行序列化,消息头包含 32 位调用 ID 和 16 位操作码。

简单横向对比不同语言技术栈()

Java

  • 核心框架:Netty(异步事件驱动网络应用框架,基于 NIO)、Vert. X(JVM 上的响应式编程工具包)
  • 并发库:java.util.concurrent 包(线程池、原子类、并发集合等) JUC 那一套
  • Web 层:Spring WebFlux(响应式 Web 框架)

Go

  • 并发原语:Goroutine(轻量级线程)+ Channel(通道)
  • Web 框架:Gin、Echo、Fiber(高性能 HTTP 框架)
  • 微服务:go-kit、go-zero、Kratos

Unity(游戏引擎专属)

  • 核心框架:Mirror(专为 Unity 打造的一站式网络游戏同步框架,解决客户端与服务器间的状态同步问题)
  • 并发模式:
  • 房主模式(Host):开房间玩家的电脑同时作为客户端和服务器,适合小范围(十几人)联机
  • 专属服务器模式(Dedicated Server):独立部署云服务器,优化后单服可支撑数百至上千人并发
  • 适用场景:中小型 Unity 联机游戏开发(如多人对战、合作闯关类)

– Python

–

  • – 异步框架:asyncio(标准库)、Tornado、Sanic、FastAPI
  • – 任务队列:Celery(结合 Redis/RabbitMQ)

–

C++

  • 网络库:libuv、libevent、libev(事件驱动库)
  • 高性能框架:Seastar(基于 C++20 的高性能异步框架)
  • 通信库:ZeroMQ、gRPC

Node. Js

  • 核心特性:事件循环、异步 I/O
  • Web 框架:Express、Koa、Fastify(高性能低开销)
  • 实时通信:Socket. Io

###

Rust

  • 异步运行时:Tokio、async-std
  • Web 框架:Axum、Warp、Actix-web

Erlang/Elixir

  • 核心特性:Actor 模型、OTP 平台(高可用与软实时)
  • 代表案例:WhatsApp、RabbitMQ(部分组件)

你可能也会喜欢...

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注