Netty in action thrid chapter 心得总结

来源:互联网 发布:姚明05-06赛季数据 编辑:程序博客网 时间:2024/05/16 11:47

第三章介绍了比较多的类,这些类是用于处理输入输出的问题。后面一一讲解:

由于netty in action是使用netty 4 版本作为讲解的。目前已经出到Netty 5了,有些内容被作废了。
比较常见的是4版本有ChannelInboundHandler 和ChannelOutboundHandler这两个基类。它们分别处理read/write
在netty5里,已经将输入输出合并在一起了ChannelHandler,目的是为了简洁。

此文还是按照4.0版本来描述,可以查阅差异
跟踪这个项目
https://github.com/netty/netty/pull/1999

既然需要ChannelHandler,就要提供方法去添加这些Handler,
采用的是ChannelInitializer类,override它的initChannel方法,
在initChannel里面,做添加Handler的工作。

如何添加呢?
又有一个类,名为ChannelPipeline,可以理解为一个管道,你可以在这个管道上添加多个Handler,有先后顺序的
之前说过,一个client对应一个Channel。
Channel的输入输出流会流过ChannelPipeline,被多个handler处理。
值得一提的是ChannelInitializer也是一个ChannelHandler,但是它的功能是添加其他handler。添加完后,它会从管道ChannelPipeline上移除。

接下来是
EventLoop和EventLoopGroup

EventLoop
1.负责管理Channel的IO操作,
2.可以同时管理多个Channel

EventLoopGroup
1.包含多个EventLoop
2.提供接口获取EventLoop

关于Channel,下面是英文解析:
A Channel is a representation of a socket connection or some component capable of performing IO operations, hence why it is managed by the EventLoop whose job it is to process IO.

netty是异步,事件驱动的network框架。所以它的IO是异步的。为了实现异步,java提供了java.util.concurrent.Future类。
Netty采用了Future,自己写了一个ChannelFutures。
Future可以理解为保存了一个操作后的结果。它有listener,当操作完成或者失败的时候,就会做notified。
使用异步,是不清楚什么时候执行操作的,只能保证说执行玩后一定会调用Future做notified

netty也是采用多线程去处理IO的。很多人觉得多线程,就要做synchronchronize同步处理。但是Netty确是不需要做同步处理的。
原因是刚才提到的
EventLoop和EventLoopGroup
每当一个Channel注册,都会把这个Channel绑定到EventLoop,一旦绑定Channel的整个生命周期都不会再改变。
而EventLoop同样的,它的生命周期是绑定到一个线程上。
这两点,导致了每一个Channel只会在绑定的一个线程做所有操作。所以不会需要同步。

而EventLoopGroup存储EventLoop,提供接口获取EventLoop

接下来讲解
Bootstrap和ServerBootstrap
两者都是用于运行netty程序的

两者的差异主要是以下:
1.Bootstrap用于客户端,连接远程服务器的host和port,
1.ServerBootstrap用于服务器,绑定本地端口

2.BootStrap只有一个EventLoopGroup
2.ServerBootStrap有两个EventLoopGroup

为什么ServerBootStrap有两个EventLoopGroup呢?
原因是作为服务端,
一个是保存ServerChannel,服务器自身的Channel;
另一个是保存Channel,客户端的Channel

服务器的Channel负责accept客户端的connection请求,
然后创建的客户端Channel会被保存在另一个EventLoopGroup上。

两个的情况下,服务器就能大量的接受connection请求。原因是假如只有一个,那么EventLoopGroup由于业务处于busy状态下,connection请求会超时。
而有专门负责接受connection请求,就不会有超时现象了。

由于多个Channel都绑定到一个EventLoop,所以任何情况下们都不要使得EVentLoop处于阻塞状态。

事实上,服务端可以只有一个EventLoopGroup。Netty允许这个EventLoopGroup做accept connection和process IO

继续说
ChannelInboundHandler和ChannelOutboundHandler

两者都是继承ChannelHandler,
都是部署在ChannelPipeline上。
采用的是链式处理,多个ChannelInboundHandler就按顺序执行完。ChannelOutboundHandler同理。

注意两种可以同时在一个ChannelPipeline部署。当是Inbound时,数据流会跳过OutboundHandler。Outbound时,同理。

当ChannelHandler加入到ChannelPipeline后,会获得变量ChannelHandlerContext,它对应一个Channel。
所以有两个地方可以使得Channel发消息。
一个是Channel本身提供的方法,
二是使用ChannelHandlerContext

两者的区别是Channel本身方法被调用是执行完ChannelPipeline,而ChannelHandlerContext是ChannelPipeline执行过程中。

编码encoders
解码decoders
编码意思是把java对象转换成字节
解码是把字节转换成java对象

使用的http,UDP,tcp等,都是编码解码后在网络上传输的,因为只有字节流才能网络传输。

netty提供了简单的编解码类
SimpleChannelInboundHandler

T代表你想转换的类型。

想要定制,就继承
ChannelInboundHandlerAdapter实现

书中再次提醒不要blocking阻塞你的ChannelHandler。如何把阻塞操作交给其他线程做呢?
netty的ChannelHandler可以指定一个EventExecutorGroup对象。它拥有EventExecutor对象。
ChannelHandler上所有methods方法都交给EventExecutor去做,EventExecutor会开一个线程去做。
其实就是把耗时的操作都交给其他线程去做了。

这章写的真累。

0 0
原创粉丝点击