Netty 简介

Netty 是一个面向 JVM 的异步事件驱动网络开发框架,目标是让高并发、高吞吐的网络程序开发像写普通业务代码一样简单。它在内部采用 Reactor/Proactor + 线程池组合,将 I/O 多路复用、缓冲区管理、协议编解码等复杂细节彻底封装,从而让开发者只需关注 ChannelHandler 里的业务逻辑。

结构速览

  • Channel:套接字抽象,支持 NIO、Epoll、KQueue、io_uring、UDT、QUIC 等多种传输
  • EventLoop/Group:事件循环线程,单线程串行化 + 任务队列,天然避免锁竞争
  • ChannelPipeline:责任链,入站/出站双向流,动态编解码、聚合、加密
  • ByteBuf / Buffer:内存模型,直接内存池、零拷贝、引用计数

关键特性

  • 非阻塞 I/O:基于 Selector(或 epoll/kqueue/io_uring)实现真正的异步读写
  • 零拷贝优化:CompositeByteBuf、FileRegion.sendfile() 及 TCP_CORK/TCP_NOPUSH
  • 自适应内存池:PooledByteBufAllocator + ThreadLocal 缓冲,避免 GC 压力
  • 丰富协议栈:内置 HTTP/1.1、WebSocket、HTTP/2
  • 平台原生加速:Linux epoll、Mac kqueue、Windows IOCP
  • 可插拔管道:Handler 动态增删、Sharable 注解、Half-close、背压机制

落地场景

  • 高吞吐 RPC:gRPC-Java、Dubbo、Finagle 均内嵌 Netty
  • 网关与反向代理:Spring Cloud Gateway、Zuul-2
  • 消息/流处理:Kafka(旧版)、Pulsar、Flink
  • 游戏与 IM:低延迟长连接

POM 依赖

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.6.Final</version>
</dependency>

服务端代码

package icu.wzk.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class WzkNettyServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        ChannelPipeline pipeline = nioSocketChannel.pipeline();
                        pipeline
                                .addLast(new StringEncoder())
                                .addLast(new StringDecoder())
                                .addLast(new SimpleChannelInboundHandler<String>() {
                                    @Override
                                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
                                        System.out.println("自定义处理器: " + s);
                                    }
                                });
                    }
                });
        ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();
        System.out.println("服务启动完毕");
        channelFuture.channel().closeFuture().sync();
    }
}

客户端代码

package icu.wzk.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;

import java.util.Date;

public class WzkNettyClient {
    public static void main(String[] args) throws Exception {
        Bootstrap bootstrap = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        bootstrap
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        channel
                                .pipeline()
                                .addLast(new StringEncoder());
                    }
                });
        Channel channel = bootstrap.connect("127.0.0.1", 8888).channel();
        while (true) {
            channel.writeAndFlush(new Date() + " Hello!");
            Thread.sleep(2000);
        }
    }
}

测试程序

服务端运行效果: 服务端启动后会监听 8888 端口,接收到客户端消息后打印”自定义处理器: ” + 消息内容

客户端运行效果: 客户端会每隔 2 秒向服务端发送一条日期时间消息