一、Netty概述
Netty是 一个异步事件驱动的网络应用程序框架(NIO 框架,Non-Blocking IO,即同步非阻塞式IO),用于快速开发协议服务器和客户端。
Netty拥有高性能、 高吞吐量,低延迟,资源消耗少,最小化不必要的内存复制等优点。
Netty本身提供了 TCP/UDP 和 HTTP 协议栈,使用方便。
二、Netty的重要组件
1.Bootstrap、ServerBootstrap
Netty 应用由 Bootstrap 开始,主要作用是配置整个 Netty 程序,其 中 Bootstrap 是客户端程序的启动引导类, ServerBootstrap 是服务端启动引导类。
例如创建并开启服务段Netty监听:
public synchronized ServerChannel startup() {
bootstrap = new ServerBootstrap();
//配置线程组、使用NioServerSocketChannel作为服务器的通道实现、设置长连接、低延迟
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
//初始化通道
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//配置通道Handler流水线
ch.pipeline().addLast(new InboundProxy2Decoder()).addLast(new IdleStateHandler(config.getReaderIdleTimeSeconds(), config.getWriterIdleTimeSeconds(), config.getAllIdleTimeSeconds()))
.addLast(tcpChannelEncoder.getMessageToByteEncoder()).addLast(tcpChannelDecoder.getByteToMessageDecoder());
ch.pipeline().addLast(new TcpChannelInboundHandler(channelEventDispatcher, tcpChannelContext));
}
});
bootstrap.bind(config.getPort());
//程序退出时执行
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
return this;
}
2.配置线程组:bootstrap.group(bossGroup, workerGroup)
启动Netty服务端,需要配置两个线程组:
bossGroup 用于监听客户端连接,专门负责与客户端创建连接,并把连接注册到workerGroup的Selector中。 workerGroup用于处理每一个连接发生的读写事件。一般直接new创建:
//设置bossGroup线程数为1
private EventLoopGroup bossGroup = new NioEventLoopGroup(1);
//workerGroup可以使用无参构造器,默认线程数cpu核数的两倍
private EventLoopGroup workerGroup = new NioEventLoopGroup();
3.设置通道类型bootstrap.channel()
//使用NioServerSocketChannel作为服务器的通道实现
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
通道类型有以下4种:
NioSocketChannel: 异步非阻塞的客户端 TCP Socket 连接。
NioServerSocketChannel: 异步非阻塞的服务器端 TCP Socket 连接。
常用的就是以上两个通道类型,因为是异步非阻塞的。所以是首选。
OioSocketChannel: 同步阻塞的客户端 TCP Socket 连接。
OioServerSocketChannel: 同步阻塞的服务器端 TCP Socket 连接。
4.option()与childOption()
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
//连接保活,默认值为False。启用该功能时,TCP会主动探测空闲连接的有效性。
.childOption(ChannelOption.SO_KEEPALIVE, true)
//立即发送数据,默认值为Ture,提高响应时间
.childOption(ChannelOption.TCP_NODELAY, true)
//配置缓冲区分配器,默认ByteBufAllocator.DEFAULT,推荐使用PooledByteBufAllocator.DEFAULT,可以减少内存碎片
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
option() 设置的是服务端用于接收客户端连接参数,也就是boosGroup线程。
childOption()设置父管道接收到的连接参数,对应workerGroup线程。
5.pipeline()和childHandler()
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
//自定义入站处理类
.addLast(new InboundProxy2Decoder())
//当通道有一段时间没有执行读、写或两个操作时触发IdleStateEvent。0标识禁用
.addLast(new IdleStateHandler(0, 0, 0))
//自定义出站处理类(主要将出站文本msg编码为ByteBuf<CompositeByteBuf>, 增加统一消息头等, 需要继承Netty提供基类MessageToByteEncoder)
.addLast(new OutboundMessageEncoderHandler())
//自定义入站处理类(主要是根据不同消息类型选择解析ByteBuf处理)
.addLa