Netty 系列文章之基本组件概览

Catalogue
  1. 1. 前言
  2. 2. 基本组件概览
    1. 2.1. Channel
    2. 2.2. EventLoop
    3. 2.3. ChannelHandler
    4. 2.4. ChannelPipeline
    5. 2.5. ChannelFuture
    6. 2.6. ByteBuf
    7. 2.7. BootStrap
  3. 3. 小结
  4. 4. 参考资料 & 鸣谢

前言

在之前的文章Netty 入门初体验简单介绍了 Netty 服务端和客户端的例子,下面依旧以Netty 服务端 demo 为例,来简单阐述下 Netty 的基本组件。

基本组件概览

以Netty服务端的一个例子来阐述其中用到的基本组件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class EchoServer {
private final int port;

public EchoServer(int port) {
this.port = port;
}

public static void main(String[] args) throws InterruptedException {
new EchoServer(8888).start();
}

public void start() throws InterruptedException {
final EchoServerHandler serverHandler = new EchoServerHandler();
//创建EventLoopGroup,处理事件
EventLoopGroup group = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group,worker)
//指定所使用的NIO传输 Channel
.channel(NioServerSocketChannel.class)
//使用指定的端口设置套接字地址
.localAddress(new InetSocketAddress(port))
//添加一个EchoServerHandler到子Channel的ChannelPipeline
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//EchoServerHandler别标志为@Shareable,所以我们可以总是使用同样的实例
socketChannel.pipeline().addLast(serverHandler);
}
});
//异步的绑定服务器,调用sync()方法阻塞等待直到绑定完成
ChannelFuture future = b.bind().sync();
future.channel().closeFuture().sync();
} finally {
//关闭EventLoopGroup,释放所有的资源
group.shutdownGracefully().sync();
worker.shutdownGracefully().sync();
}
}
}

服务端创建流程:

  • 创建 ServerBootStrap实例
  • 设置并绑定 NioEventLoopGroup线程池
  • 通过 ServerBootStrapchannel方法设置并绑定服务端 Channel
  • 创建并初始化 ChannelPipeline
  • 添加并设置 ChannelHandler
  • 绑定并启动监听端口

上面简述了服务端的创建流程,其中包含了 Netty的基本组件的使用,下面这张导图也简单的叙述了Netty各大组件的概念与作用

netty

Channel

Channel是 Netty中的网络操作抽象类,对应JDK底层的Socket,它除了包含基本的I/O操作,如 bind(),connect(),read(),write()之外,还包括了Netty框架相关的一些功能,如获取 Channel的EventLoop。

EventLoop

EventLoop定义了Netty的核心抽象,用于处理连接的生命周期中所发生的事件。EventLoop 为Channel处理I/O操作,下图是 Channel,EventLoop,Thread以及EventLoopGroup之间的关系(摘自《Netty In Action》):

eventloop

这些关系是:

  • 一个EventLoopGroup 包含一个或者多个EventLoop
  • 一个 EventLoop 在它的生命周期内只和一个Thread绑定
  • 所有由 EventLoop处理的 I/O事件都将在它专有的Thread上被处理
  • 一个 Channel 在它的生命周期内只注册一个EventLoop
  • 一个 EventLoop 可能会被分配给一个或多个 Channel

EventLoopGroup实际上就是处理I/O操作的线程池,负责为每个新注册的Channel分配一个EventLoop,Channel在整个生命周期都有其绑定的 EventLoop来服务。

而上面服务端用的 NioEventLoop 就是 EventLoop的一个重要实现类,NioEventLoop 是Netty内部的I/O线程,而 NioEventLoopGroup是拥有 NioEventLoop的线程池,在Netty服务端中一般存在两个这样的NioEventLoopGroup线程池,一个 “Boss” 线程池,用于接收客户端连接,实际上该线程池中只有一个线程,一个 “Worker”线程池用于处理每个连接的读写。而Netty客户端只需一个线程池即可,主要用于处理连接中的读写操作。

ChannelHandler

ChannelHandler是Netty的主要组件,它主要用于对出站和入站数据进行处理,它有两个重要的子接口:

  • ChannelInboundHandler——处理入站数据以及各种状态变化
  • ChannelOutboundHandler——处理出站数据并且允许拦截所有的操作

ChannelPipeline

ChannelPipeline提供了 ChannelHandler链的容器,换句话说,就是一个逻辑处理链,用于拦截流经Channel的入站和出站事件的ChannelHandler。还是就是当 Channel被创建时,它会被自动地分配到它的专属的 ChannelPipeline。
channelpipline

当一个消息或者任何其他的入站事件被读取时,那么它会从 ChannelPipeline的头部开始流动,并被传递给第一个 ChannelInboundHandler,第一个处理完成之后传递给下一个 ChannelInboundHandler,一直到ChannelPipeline的尾端,与之对应的是,当数据被写出时,数据从 ChannelOutboundHandler 链的尾端开始流动,直到它到达链的头部为止。

ChannelFuture

Netty中所有I/O操作都是异步的,使用ChannelFuture可以获取操作完成的结果,其 addListener()方法注册了一个 ChannelFutureListener,以便在某个操作完成时(无论是否成功)得到通知。

ByteBuf

ByteBuf是Netty中的字节缓冲区,相比于Java NIO中的 ByeBuffer,ByteBuf做了很多改进,ByteBuf的功能性和灵活性更好。

BootStrap

Netty提供的启动辅助类,帮助Netty客户端或服务端的Netty初始化,服务端对应的是 ServerBootStrap引导类。

小结

上面简单的介绍了Netty的一些基本组件,后续文章会详细对每个组件进行分析

参考资料 & 鸣谢

Bagikan Komentar