线程模型配置提升性能
- NioEventLoopGroup
- 说明:Netty通过
NioEventLoopGroup
来管理I/O线程。在服务端,通常会创建两个NioEventLoopGroup
,一个用于接收客户端连接(Boss Group),另一个用于处理I/O读写操作(Worker Group)。合理设置线程数量对性能影响很大。
- 示例:
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(8);
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("Received: " + msg);
}
});
}
});
ChannelFuture f = b.bind(8888).sync();
f.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
- 在上述代码中,
bossGroup
设置为1个线程,因为它主要负责接收连接,通常不需要太多线程。workerGroup
设置为8个线程,具体数量可根据服务器CPU核数、业务处理复杂度等因素调整,一般可以设置为Runtime.getRuntime().availableProcessors() * 2
。
- Reactor模式
- 说明:Netty基于Reactor模式实现,通过将I/O操作的多路复用、事件分发和处理分离,提升性能。
NioEventLoop
会不断轮询注册在其上的Selector
,当有事件到达时,将事件分发给对应的ChannelHandler
处理。
- 示例:上述代码中,
NioEventLoopGroup
中的NioEventLoop
就是Reactor模式的具体实现,NioEventLoop
管理Selector
,对I/O事件进行处理和分发。
缓冲区配置提升性能
- ByteBuf
- 说明:Netty使用
ByteBuf
作为缓冲区,它提供了比Java原生ByteBuffer
更灵活和高效的操作方式。ByteBuf
有堆内存、直接内存和复合缓冲区等类型。
- 示例:
ByteBuf buffer = Unpooled.buffer(1024);
buffer.writeBytes("Hello, Netty!".getBytes(StandardCharsets.UTF_8));
byte[] array = new byte[buffer.readableBytes()];
buffer.getBytes(buffer.readerIndex(), array);
System.out.println(new String(array, StandardCharsets.UTF_8));
buffer.release();
- 在这个例子中,首先创建了一个容量为1024字节的
ByteBuf
,然后写入字符串数据,接着从ByteBuf
中读取数据到字节数组并打印。ByteBuf
在内存管理上比ByteBuffer
更方便,它有独立的读、写指针,避免了ByteBuffer
在读写切换时调用flip()
方法的繁琐操作。
- 池化
- 说明:Netty支持
ByteBuf
的池化,通过复用缓冲区对象,减少内存分配和垃圾回收开销,提升性能。
- 示例:
ByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;
ByteBuf buffer = allocator.heapBuffer(1024);
try {
buffer.writeBytes("Hello, Pooled ByteBuf!".getBytes(StandardCharsets.UTF_8));
// 处理数据
} finally {
buffer.release();
}
- 上述代码使用
PooledByteBufAllocator
创建了一个池化的ByteBuf
,使用完后需要调用release()
方法将其归还到池中,以便复用。