全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 8 分钟 ✍️ juanwangdev

Java IO与网络性能优化

IO操作是系统性能瓶颈,优化IO能显著提升吞吐量。

IO模型对比

模型特点适用场景
BIO阻塞,一连接一线程连接数少
NIO非阻塞,多路复用连接数多
AIO异步,回调通知高并发场景

NIO核心组件

Buffer缓冲区

Java
ByteBuffer buffer = ByteBuffer.allocate(1024);

// 写入数据
buffer.put(data);

// 切换读模式
buffer.flip();

// 读取数据
byte[] output = new byte[buffer.remaining()];
buffer.get(output);

// 清空/重用
buffer.clear();

// 直接缓冲区(零拷贝)
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);

Channel通道

Java
// 文件Channel
FileChannel fileChannel = new FileInputStream("file.txt").getChannel();

// Socket Channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);  // 非阻塞

// ServerSocket Channel
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(8080));

Selector选择器

Java
Selector selector = Selector.open();

// 注册Channel
channel.register(selector, SelectionKey.OP_READ);

// 选择就绪Channel
while (selector.select() > 0) {
    Set<SelectionKey> keys = selector.selectedKeys();
    for (SelectionKey key : keys) {
        if (key.isAcceptable()) {
            // 处理连接
        }
        if (key.isReadable()) {
            // 处理读取
        }
        if (key.isWritable()) {
            // 处理写入
        }
    }
    keys.clear();
}

零拷贝技术

传统IO拷贝流程

Java
磁盘 → 内核缓冲区 → 用户缓冲区 → 内核缓冲区 → 网卡
      (DMA拷贝)    (CPU拷贝)    (CPU拷贝)   (DMA拷贝)

总共4次拷贝,4次上下文切换

零拷贝优化

Java
// FileChannel.transferTo(sendfile)
FileChannel source = new FileInputStream("source.txt").getChannel();
SocketChannel dest = SocketChannel.open(new InetSocketAddress("host", 80));
source.transferTo(0, source.size(), dest);

// 拷贝流程:
// 磁盘 → 内核缓冲区 → 网卡
// (DMA拷贝) (DMA拷贝)
// 2次拷贝,2次上下文切换

mmap内存映射

Java
// mmap:文件映射到内存
MappedByteBuffer mappedBuffer = new RandomAccessFile("file.txt", "r")
    .getChannel()
    .map(FileChannel.MapMode.READ_ONLY, 0, fileSize);

// 直接访问内存,无拷贝
mappedBuffer.get(bytes);

文件IO优化

缓冲读写

Java
// 不推荐:无缓冲
InputStream in = new FileInputStream("file.txt");
int b = in.read();  // 每次系统调用

// 推荐:缓冲流
BufferedInputStream buffered = new BufferedInputStream(in);
int b = buffered.read();  // 批量读取,减少系统调用

// 推荐:NIO FileChannel
FileChannel channel = new FileInputStream("file.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(8192);
channel.read(buffer);

批量读写

Java
// 批量读取大文件
ByteBuffer buffer = ByteBuffer.allocateDirect(64 * 1024);  // 64KB直接缓冲
while (channel.read(buffer) != -1) {
    buffer.flip();
    processBuffer(buffer);
    buffer.clear();
}

// 批量写入
ByteBuffer[] buffers = new ByteBuffer[10];
channel.write(buffers);  // 批量写入

网络IO优化

NIO服务端实现

Java
public class NioServer {
    public void start(int port) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress(port));
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();

                if (key.isAcceptable()) {
                    SocketChannel client = serverChannel.accept();
                    client.configureBlocking(false);
                    client.register(selector, SelectionKey.OP_READ);
                }

                if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int len = client.read(buffer);
                    if (len > 0) {
                        buffer.flip();
                        client.write(buffer);
                    }
                }
            }
        }
    }
}

Netty优化配置

Java
// Netty高性能配置
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();  // 默认CPU核数*2

ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
    .channel(NioServerSocketChannel.class)
    .option(ChannelOption.SO_BACKLOG, 1024)  // 连接队列大小
    .option(ChannelOption.SO_REUSEADDR, true)  // 端口复用
    .childOption(ChannelOption.TCP_NODELAY, true)  // 禁用Nagle
    .childOption(ChannelOption.SO_KEEPALIVE, true)  // 保持连接
    .childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel ch) {
            ch.pipeline().addLast(new MyHandler());
        }
    });

网络参数优化

TCP参数

Bash
// Socket选项设置
Socket socket = new Socket();

// 发送缓冲区
socket.setSendBufferSize(64 * 1024);

// 接收缓冲区
socket.setReceiveBufferSize(64 * 1024);

// 禁用Nagle算法(减少小包延迟)
socket.setTcpNoDelay(true);

// 连接超时
socket.setSoTimeout(5000);

// 保持连接
socket.setKeepAlive(true);

系统参数(Linux)

Java
# 文件句柄数
ulimit -n 100000

# TCP参数
sysctl -w net.core.somaxconn=65535       # 连接队列
sysctl -w net.ipv4.tcp_max_syn_backlog=65535  # SYN队列
sysctl -w net.ipv4.tcp_tw_reuse=1        # TIME_WAIT复用
sysctl -w net.ipv4.tcp_fin_timeout=30    # FIN超时

异步IO(AIO)

text
// AIO异步文件读写
AsynchronousFileChannel channel = AsynchronousFileChannel.open(
    Path.of("file.txt"), StandardOpenOption.READ);

ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> future = channel.read(buffer, 0);  // 异步读取

// 回调方式
channel.read(buffer, 0, null, new CompletionHandler<Integer, Void>() {
    @Override
    public void completed(Integer result, Void attachment) {
        System.out.println("读取完成: " + result);
    }

    @Override
    public void failed(Throwable exc, Void attachment) {
        exc.printStackTrace();
    }
});

IO优化总结

优化点方法
减少拷贝transferTo、mmap、DirectBuffer
减少系统调用BufferedInputStream、批量读写
高并发网络NIO Selector、Netty
减少小包延迟TCP_NODELAY
连接复用KeepAlive、连接池

注意事项

直接缓冲区分配开销大,适合长生命周期

NIO适合连接数多,BIO适合连接数少

零拷贝需要操作系统支持(Linux sendfile)

Netty默认已优化大部分参数

避免频繁创建销毁连接,使用连接池

要点总结

  1. NIO多路复用适合高并发,一个线程管理多个连接
  2. 零拷贝用transferTo/mmap减少数据拷贝和上下文切换
  3. DirectBuffer堆外内存,减少GC压力
  4. TCP_NODELAY禁用Nagle,减少小包延迟
  5. Netty封装NIO,生产推荐使用

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java适配器模式
下一篇 → Java JVM内存模型与调优
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库