Netty敲完代码还是一脸蒙蔽,几个核心的类到底是干啥的?
Netty将核心的功能逻辑抽象有好几个组件,为了更容易理解,下面先讲下面5个组件。
下面这些描述,对于初学者看完可能还是一脸蒙蔽,不急,再下面会慢慢解释其相关意思。
- channel : 一个连接到网络的套接字或能够进行一系列读、写、连接和绑定等IO操作的组件。
- EventLoop: EventLoop是 处理注册到自己本身上面的channel所有IO操作。
- EventLoopGroup: EventLoopGroup是一组EventLoop。
- ChannelHandler:ChannelHandler是处理IO事件或拦截一个IO操作,并将其转发到ChannelPipeline中的下一个ChannelHandler处理程序(责任链模式)。
- ChannelPipeline: ChannelPipeline是一个ChannelHandler的列表(List)
(还有一个BootStrap类就是将上面的组件组装,让程序跑起来的,这里暂不说明。)
- 首先先看看一个原始的网络IO(暂时以AIO来讲述,比较好理解, netty支持AIO与NIO),当一个客户端和一个服务端进行网络通信的时候,其实就是2个Socket在通信,然后在线程里面处理Sokcet的相关通信(业务)逻辑
AIO例子代码如下,熟悉的可直接跳过。
//客户端
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 8080);
InputStream inputStream = socket.getInputStream();
BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
String s = bf.readLine();
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//服务端
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8080);
while (true){
Socket socket = serverSocket.accept();
new Thread(new TimeServerHandler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(serverSocket != null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.而Netty大致将上面的一个流程抽象如下(个人理解,重要)
- socket抽象成Channel
- 线程抽象EventLoop
- 线程的处理逻辑 抽象成了ChannelPipeline
3.Netty本身的一个流程
- 当有新的链接发生时候,会生成一个新的channel, 然后channel初始化后会注册到EventLoop上.
- EventLoop管理着Channel的所有IO操作/事件,将对应的事件作出不同的行为。例如channel出了读事件,EventLoop将读取到的数据传送到ChannelPipeline.
注意:
- 一个channel只会注册到一个EventLoop上,而一个EventLoop可以管理多个channel。
- 一个EventLoop在它的生命周期只和一个Thread绑定(这么做的原因是一个channel的所有IO操作都是由同一个Thread处理,实际上消除了同步的需要。也由于同一个线程处理,对于一个EventLoop来说,同时处理多个channel,在一定程度上规避了线程上下文的切换,提高性能)。
- 最后注意的是一个EventLoop在它的生命周期只和一个Thread绑定,EventLoop处理着多个channel的IO操作,所以在我们编写ChannelHandler逻辑的时候,永远不要将时间执行过长的逻辑放到ChannelHandler里面,因为它将阻塞需要在同一线程上执行的其他任务,时间执行过长的逻辑建议使用EventExecutor额外处理。
4.一些思考
那么抽象成这些后又什么好处?
- 兼容多种IO模型,对于channel来说,使用什么IO模型,就使用对应的IO模型的channel,对于EventLoop也一样。而代码实现上,Netty对于不同的IO模型,实现的时候只要实现对应的
Channel、EventLoop的逻辑即可,扩展也好扩展。 - 统一接口,不管是什么IO模型,我们使用起来差不不大,易于维护。
不知道你看完上面的说明再看这个描述会不会更好理解,为了方便阅读就我搬下来了:
- channel : 一个连接到网络的套接字或能够进行一系列读、写、连接和绑定等IO操作的组件。
- EventLoop: EventLoop是 处理注册到自己本身上面的channel所有IO操作。
- EventLoopGroup: EventLoopGroup是一组EventLoop。
- ChannelHandler:ChannelHandler是处理IO事件或拦截一个IO操作,并将其转发到ChannelPipeline中的下一个ChannelHandler处理程序(责任链模式)。
- ChannelPipeline: ChannelPipeline是一个ChannelHandler的列表(List)