通过Netty入门,可以运行和启动一个简单的客户端和服务端的应用了,这里看下Netty每个组件的细节,以及组件之前是如何协作的。
实例
我们先看代码:注释中包含了使用Netty服务端的一些操作说明,刚学的时候不太明白这些东西的意思,但是看了Netty的组件设计,及其架构,就容易理解每个语句对应的意思。
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
// 服务端的BootStrap,一个需要接受连接,一个用来处理事件
b.group(bossGroup, workerGroup)
// Channel理解为通道,网络传输的通道类型
.channel(NioServerSocketChannel.class)
// ChannerlHandler要被装进ChannelPipeline
// 而过程则是调用ChannelInitializer的iniChannel方法
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
// addLast,在PipeLine中的Handler是有顺序的,所以
// 有addLast,addFirst等方法
// 添加的同时,可以指定Encoder和Decoder
ch.pipeline().addLast(new RequestDecoder(),
new ResponseDataEncoder(),
new ProcessingHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// TODO 待细看,先当做固定的写法
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
客户端与服务端基本一致,只是将绑定本地端口换成了连接远端的端口
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
// 配置ChannelHandler
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(new RequestDataEncoder(),
new ResponseDataDecoder(), new ClientHandler());
}
});
ChannelFuture f = b.connect(host, port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
下面是看Netty In Action一书中整理到的其组件设计的一些知识点。
Netty网络层
Channel,EventLoop,ChannelFuture可以看做Netty的网络抽象层
- Channel - Socket
- EventLoop - 控制流,多线程,并发
- ChannelFuture - 异步通知
Channel接口
基础的IO操作,bind,connect,read,write. 在底层上,这些主要依赖Java的Socket,Netty的Channel封装了底层的复杂操作。使得用起来简化很多,它提供了很多预定义的特定场景下的实现。
image.pngEventLoop接口
EventLoop接口定义了连接的整个生命周期中的事件处理,下图解释了Channel,EventLoop,Threads和EventLoopGroup的关系
image.png- EventLoopGroup包含一个或多个EventLoop
- EventLoop的整个生命周期与单个线程的生命周期一致
- Channel注册它的生命周期到单个的EventLoop上
- 单个EventLoop能分配一个或多个Channel
- 所有的I/O事件被EventLoop处理
ChannelFuture
在Netty中,所有的IO操作都是异步的,因为操作不是立刻返回结果,我们需要一个方式在程序执行一会再获取结果。Netty提供了ChannelListener,它的addListner方法注册一个ChannelFutureListener,当操作完成的时候就会通知Listener。
ChannelHandler and ChannelPipeline
这两个组件用来管理数据流和执行应用的逻辑。
ChannelHandler
从开发者的角度来看,Netty最主要的组件就是ChannelHandler,它可以处理应用内输入和输出的数据流,基本上可以做任意类型的数据操作,例如数据格式转换,或者异常处理。
ChannelPipeline
ChannelPipeline提供了ChannelHandler的容器,其内部可以有多个ChannelHandler,定义了链式ChannelHandler传播输入数据和输出数据流的API。当Channel被创建的时候,它会自动的分配到ChannelPipeline。
- ChannelInitializer的实现被注册到ServerBootstrap
- 当ChannelInitializer.initChannel被调用,就将多个ChannelHandler安装到pipeline中
- ChannelInitializer将自己从ChannelPipeline中移除
ChannelHandler可以看做是代码的容器,里面主要都是我们的程序逻辑,处理事件还有在ChannelPipeline中的数据,ChannelHandler主要被添加进ChannelPipeLine中,当它被添加的时候会被分配一个ChannelHandlerContext。
小结
这里主要介绍了Netty的一些基本组件。
参考
- 《Netty in Action》
网友评论