netty的简单使用指南(含对nio的对比)

数据结构1:

BOSS线程池:
EventLoopGroup bossLoopGroup = new NioEventLoopGroup(1);
BOSS线程池中有一条线程工作,就是发现新的连接。 所以一个线程就够了。
Netty是支持同时监听多个端口的,所以BOSS线程池的大小按照需要监听的服务器端口数量进行设置就行了。 一般是1

工作线程池:
EventLoopGroup workLoogGroup = new NioEventLoopGroup(processorsNumber * 2, threadFactory, SelectorProvider.provider());
work线程池的大小,这个大小一般是物理机器/虚拟机器 可用内核的个数 *  2
work线程池中的线程(如果封装的是JAVA NIO,那么具体的线程实现类就是NioEventLoop)
负责 channel 事件监听,并根据事件状态,调用不同的事件就绪后的处理方法 ChannelHandler。  

两个线程池的设计 把nio 中selector的角色分成针对OP_ACCEPT 事件是BOSS线程来执行监听的。
而读写事件是用work线程来轮询监听的。

所以说netty 封装了一个线程池来处理 数据读写事件就绪 以及 真实的读写事件。

/指定Netty的Boss线程和work线程 和配置nio模型
serverBootstrap.group(bossLoopGroup, workLoogGroup);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
serverBootstrap.bind(new InetSocketAddress("0.0.0.0", 83));

具体使用流程是:(基于nio模型)

1. BOSS线程负责发现连接到服务器的新的channel(类比nio中SocketServerChannel的ACCEPT事件),并且将这个channel经过检查后 注册到WORK连接池 的某个线程中。
2. WORK线程 发现操作系统有一个它感兴趣的IO事件就绪时(类比nio中SocketChannel的READ事件)则调用相应的ChannelHandler事件。当某个channel失效后(例如显示调用ctx.close())这个channel将从绑定的EventLoop中被剔除。(nio中需要自己编写方法,进行读写操作。)
3. 一个Work线程池的线程将按照底层nio的Selector的事件状态,决定执行ChannelHandler中的哪一个事件方法 channelRegistered、channelUnregistered、channelActive、channelInactive。 重要的是channelRead  channelReadComplete这两个。
TCPServerHandler 继承ChannelInboundHandlerAdapter 作为助手来提供以上方法。这个助手要注册在每个channel中。

4. 执行完成后,work线程将一直轮询 直到该work线程所管理的channel 发生了新的IO事件。

所以nio默认没有提供线程池,真正的读写事件需要自己使用线程池来做。 而netty就默认提供线程池 worker线程。

数据结构2:
Channel:
Channel 其实就是每个socket连接的封装。
每一个channel,都有独立的handler、ChannelHandlerContext、ChannelPipeline、Attribute
每个ChannelPipeline 都可以添加多个handler。用来对该channel 做处理。

ChannelHandler:
handler这种叫法就是给用户提供处理的地方。
在ChannelPipeline中,有若干的过滤器。我们称之为“ChannelHandler”(处理器或者过滤器)。
用于处理/过滤 流入数据的ChannelHandler,称之为“ChannelInboundHandler”
用于处理/过滤 流出数据的ChannelHandler,称之为“ChannelOutboundHandler”
数据在ChannelPipeline中有一个一个的Handler进行处理,并形成一个新的数据状态

实现我们自己业务的“数据流入处理器:
我们可以实现ChannelInboundHandler接口或者ChannelOutboundHandler接口,
来实现我们自己业务的“数据流入处理器”或者“数据流出”处理器。

消息协议:
也采用ChannelHandler的形式通过ChannelPipeline 来添加。

具体有几种:
HttpRequestDecoder/HttpResponseEncoder:
实现了Http协议的数据输入格式的解析。这个类将数据编码为HttpMessage对象,并交由下一个ChannelHandler进行处理。 反之将 服务器端HttpReponse对象的描述转换成ByteBuf对象形式

ByteArrayDecoder/ByteArrayDecoder :
最基础的数据流输入处理器,将所有的byte转换为ByteBuf对象
(一般的实现类是:io.netty.buffer.UnpooledUnsafeDirectByteBuf)。我们进行一般的文本格式信息传输到服务器时,最好使用这个Handler将byte数组转换为ByteBuf对象。

DelimiterBasedFrameDecoder:
这个数据流输入处理器,会按照外部传入的数据中给定的某个关键字符/关键字符串,重新将数据组装为新的段落并发送给下一个Handler处理器。后文中,我们将使用这个处理器进行TCP半包的问题。

支持标准数据格式解析的处理器:
例如支持Google Protocol Buffers 数据格式解析的ProtobufDecoder和ProtobufVarint32FrameDecoder处理器。
 还有支持标准的编码成Google Protocol Buffers格式、JBoss Marshalling 格式、ZIP压缩格式的ProtobufEncoder、ProtobufVarint32LengthFieldPrepender、MarshallingEncoder、JZlibEncoder等

Protobuf数据协议的集成:Netty利用自身的Channelpipeline的设计,对Protobuf数据协议进行了无缝结合。
Boss Marshalling数据协议的集成:JBoss Marshalling 是一个Java对象的序列化API包,修正了JDK自带的序列化包的很多问题,又保持跟 java.io.Serializable 接口的兼容。Netty通过封装这个协议,可以帮助我们在客户端-服务端简便的进行对象系列化和反序列化。
HTTP Request / HTTP Response 协议的集成:在Netty中,可以方便的接受和发送Http协议。也就是说,我们可以使用Netty搭建自己的WEB服务器,当然您还可以根据自己的业务要求,方便的设计类似于Struts、Spring MVC这样的WEB框架。

nio 与 netty对比。
“技术层”框架本身只对IO模型技术实现进行了封装,并不关心IO模型中流淌的数据格式
“业务层”框架对数据格式也进行了处理,线程池进行了处理,让我们可以抽出精力关注业务本身。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值