Netty学习笔记

  Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。

何为事件驱动

事件处理的两道工序:

方法 说明
事件分离器(Event Demultiplexer)   将事件源(socket/file)的I/O时间分离出来(IO就绪事件,IO完成事件),并分传递到对应的I/O事件处理器。  
事件处理器(Event Handler)   应用预先注册需要处理的事件及其事件处理器(回调函数)。  

事件分离器的两种模式:

模式 说明
Reactor   事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。I/O操作由应用完成,调用事件处理器时,表示I/O就绪。  
Proactor   demultiplexor事件处理器负责发起异步I/O操作,将用户定义的数据缓冲区地址和数据大小传递给操作系统,操作系统进行I/O操作,事件分离器捕获IO操作完成事件,然后将事件传递给对应处理器。I/O操作由系统完成,调用事件处理器时,表示I/O完成。  
何为异步I/O

  常见的I/O模式有一下几种,Netty是多路复用模式。假设场景:用户想从水管管道取5000L水,但是这个水管的水流是断断续续的,那么他有以下几种方法:

模式 大白话 说明
阻塞 I/O(blocking IO)   他打开水龙头,在必须原地等待水量达到5000L,然后这个任务才完成。   阻塞,同步I/O  
非阻塞 I/O(nonblocking IO)   他打开水龙头,然后去做别的事情,两分钟过来查看一次(轮询),直到水位达到500L,然后这个任务才完成。   非阻塞,同步I/O  
I/O 多路复用( IO multiplexing)(事件驱动I/O)   他加装多个水龙头,然后在水龙头的前端安装水滴传感器(阻塞),他在后台轮询各个传感器的数据,一旦得到A水龙头的水滴传感器已经被触发时,他就打开水龙头A接水,有一下几种机制select,epoll,iocp,kqueue,poll。   非阻塞,同步I/O  
信号驱动 I/O( signal driven IO)   他加装多个水龙头,然后在水龙头的前端安装水滴传感器,当水龙头A的水滴传感器触发时,主动通知他,他就打开水龙头A接水。   非阻塞,同步I/O  
异步 I/O(asynchronous IO)   他加装多个水龙头,然后在水龙头的前端安装水量传感器,并且将水龙头打开,然后他就去做其他的事情了,当水来时,水量传感器统计已取的水量,达到5000L时,将多个水桶的水汇聚到一个桶里,让他直接使用   非阻塞,异步I/O  
I/O多路复用模式 模式 方法 说明 最大连接数 效率 消息传递方式
select   轮询   同步非阻塞   FD_SETSIZE宏定义   FD的增加会造成线性遍历速度慢的“线性下降性能问题”   内核需要将消息传递到用户空间,都需要内核拷贝动作  
kQueue   回调   同步非阻塞   与epoll相似   与epoll相似   与epoll相似  
iocp   通知   异步   待了解   待了解   待了解  
poll   轮询   同步非阻塞   基于链表来存储没有最大连接数的限制   与select一样   与select一样  
ePoll   回调   同步非阻塞   连接数有上限,效率与连接数成反比   socket活跃大会有性能问题   通过内核和用户空间共享一块内存来实现  
Netty示例解析

以下是一个经典示例:

import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.mqtt.MqttDecoder; import io.netty.handler.codec.mqtt.MqttEncoder; import io.netty.handler.timeout.IdleStateHandler; import org.springframework.beans.factory.annotation.Autowired; import org.yb.iot.mqtt.handler.ChannelPipelineHandler; import org.yb.iot.mqtt.handler.InboundMessageHandler; import java.util.concurrent.TimeUnit; public class NettyServer { public static void main(String[] args) { /** * NioEventLoopGroup是处理I / O操作的多线程事件循环,多种实现可选。 * 使用多少个线程以及如何将它们映射到创建的通道取决于EventLoopGroup实现,甚至可以通过构造函数进行配置。 * 在上文中提到,I/O多路复用机制有多种,Netty中提供了多种实现,,以Group尾缀的为多线程实现。 */ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { /** * 设置服务器的帮助程序类。 */ ServerBootstrap serverBootstrap = new ServerBootstrap(); /** * bossGroup通常称为“老板”,接受传入的连接。 * workerGroup通常称为“工人”,一旦老板接受连接并将注册的连接注册给工人,便处理已接受连接的流量。 */ serverBootstrap.group(bossGroup, workerGroup) /** * 指定IO模型 */ .channel(NioServerSocketChannel.class) /** * 配置自定义的事件处理器。 */ .childHandler(new ChannelInitializer<SocketChannel>() { @Autowired private InboundMessageHandler inboundMessageHandler; /** * 初始化channel模型的上下文 * @param socketChannel * @throws Exception */ @Override public void initChannel(SocketChannel socketChannel) { /** * 事件处理器责任链,可以动态增删 * 可以进行例如协议编码解码,心跳,内容长度,粘包分包处理,读写处理等, * Netty已经默认提供了多种标准协议的解码编码实现,全都在io.netty.handler.codec.*下,如MQTT,HTTP等。 */ ChannelPipeline pipeline = socketChannel.pipeline(); /** 最大内容长度 */ pipeline.addLast(new HttpObjectAggregator(1024 * 1024 * 64)); /** 心跳时间 */ pipeline.addLast("idleStateHandler", new IdleStateHandler(120, 120, 120, TimeUnit.SECONDS)); /** 协议编码 */ pipeline.addLast(MqttEncoder.INSTANCE); /** 协议解码 */ pipeline.addLast(new MqttDecoder(1024 * 1024 * 64)); /** 消息处理 */ pipeline.addLast(inboundMessageHandler); } }) /** * 配置EventLoopGroup模型的参数 */ .option(ChannelOption.SO_BACKLOG, 128) /** * 配置Channel模型的参数 */ .childOption(ChannelOption.SO_KEEPALIVE, true); /** * 绑定并开始接受传入的连接,ChannelFuture支持I/O完成事件监听。 */ ChannelFuture channelFuture = serverBootstrap.bind(1883).sync(); /** * 注册等待Socket服务器关闭。 */ channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { /** * 优雅的关闭并退出服务 */ workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwjyw.html