Skip to content

1. 资源层面

  • Linux 调优(单机 1000 w 连接典型参数)
    ulimit -n 1048576              # 进程 fd 上限
    echo "* soft nofile 1048576" >> /etc/security/limits.conf
    net.ipv4.ip_local_port_range = 1024 65535
    net.ipv4.tcp_tw_reuse = 1
    net.core.somaxconn = 32768
    net.netfilter.nf_conntrack_max = 2000000
  • 多网卡 + SO_REUSEPORT
    8 个监听端口绑定同一端口,内核级负载均衡

2. Netty 代码层面

① 主从 Reactor

java
EventLoopGroup boss = new NioEventLoopGroup(1);   // 只负责 accept
EventLoopGroup worker = new NioEventLoopGroup(0); // 0=CPU*2 负责 I/O
ServerBootstrap b = new ServerBootstrap()
    .group(boss, worker)
    .channel(NioServerSocketChannel.class)
    .childOption(ChannelOption.TCP_NODELAY, true)
    .childOption(ChannelOption.SO_KEEPALIVE, true)
    .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
        new WriteBufferWaterMark(32 * 1024, 128 * 1024)); // 防止内存暴涨

② 心跳 + 空闲检测

java
pipeline.addLast(new IdleStateHandler(25, 0, 0, TimeUnit.SECONDS));
// 服务端 25 秒没收到 ping 就触发 userEventTrigger

③ 对象池化

java
msg = RECYCLER.get();          // 使用 Recycler 减少 GC
buf = PooledByteBufAllocator.DEFAULT.directBuffer(); // 堆外内存池

④ 无锁化设计

  • 一个 Channel 始终绑定同一个 EventLoop,所有操作单线程串行执行,避免锁
  • 千万连接 ≠ 千万线程,连接数与线程数解耦

3. 架构层面

  • 集群化:LVS/DPVS → 多台 Netty 网关 → Redis 存储会话
  • 心跳合并:每 30 秒一次批量 ping,减少空包流量
  • 灰度断开:利用 channel.attr() 打标,按版本逐步释放,避免瞬时重连风暴

4. 实测数据

阿里云 ecs.ebmg5(96 vCPU 384 G)

  • 单实例 1200 w 长连接,内存占用约 240 G(每条连接 ≈ 20 KB)
  • QPS 心跳 40 w/s,CPU 65 %,P99 延迟 2 ms

背诵金句
“秒传靠 hash 秒检,断点靠 分片+BitSet
千万长连接靠 Linux 调优 + 主从 Reactor + 无锁单线程 + 心跳池化。”