设为首页 加入收藏

TOP

Netty源码学习3——Channel ,ChannelHandler,ChannelPipeline(一)
2023-09-09 10:26:03 】 浏览:111
Tags:Netty Channel ChannelHandler ChannelPipeline

系列文章目录和关于我

零丶引入

Netty源码学习2——NioEventLoop的执行中,我们学习了NioEventLoop是如何进行事件循环以及如何修复NIO 空轮询的bug的,但是没有深入了解IO事件在netty中是如何被处理的,下面我们以服务端demo代码为例子,看下和IO事件处理密切的Channel

image-20230827172001638

如上在编写netty 服务端的时候,我们一般只需要指定Channel类型,以及实现ChannelHandler在对应方法中编写业务逻辑代码即可。

在Netty中,NioEventLoop是事件的调度中心,它控制了Io事件和其他任务的调度,但是io事件的处理是依赖ChannelHandler的,多个ChannelHandler又由ChannelPipline组装成流水线依次执行

这篇博客我们以此为切入点,看看Channel是如何初始化的,如何和EventLoop关联起来的,后续看看ChannelPipline是如何组织ChannelHandler的。

一丶Channel概述

Channel是Netty抽象出来的对网络I/O进行读写的相关接口,与JDK NIO中的Channel接口类似。Channel的主要功能有网络I/O的读写绑定端口客户端发起连接主动关闭连接获取通信双方网络地址等。

下面是NioServerSocketChannel,和NioSocketChannel的类图

image-20230827173532237
  • ChannelOutboundInvoker:定义了bind,connect,disconnect,close等方法。

  • Channel:Netty抽象出来的对网络I/O进行读写的相关接口,其中有两个关键的方法

    image-20230827174534161

    可看出EventLoop和Channel的关系——Channel是注册到EventLoop中的。

    ChannelPipeline和Channel的关系——每一个Channel会分配一个ChannelPipline。

  • AbstractChannel:Channel基本的实现,在其中有几个重要的属性:

    image-20230827175209476
    • unsafe:非jdk中的unsafe,这是netty定义的unsafe,其中定义了bind,connect等方法,在实际和网络打交道的时候会使用到
    • DefaultChannelPipeline:ChannelPipeline的默认实现,这就是Channel分配的ChannelPipline
    • EventLoop:此Channel注册到的EventLoop
  • AbstractNioChannel:使用Selector进行IO多路复用的Channel,其中有两个重要的属性

    image-20230827175848808

    从此可与看出,Netty中的Nio Channel 和 jdk中Channel的关系,它们是一对一的

    AbstractNioChannel拥有NIO的Channel,具备NIO的注册、连接等功能。但IO的读写交给了其子类。

  • AbstractNioByteChannel&AbstractNioMessageChannel

    AbstractNioByteChannel是面向字节的,通常是客户端进行使用,AbstractNioMessageChannel面向消息,通过是服务端进行使用。为什么netty这样设计昵?

    通常情况下,客户端只需要发送消息,因此直接将消息内容转换为字节流进行输出即可,这时候使用AbstractNioByteChannel更为合适。
    
    服务端在接收到客户端的消息后,需要对消息进行解码、反序列化、处理等操作,这时候使用AbstractNioMessageChannel更为合适。因为AbstractNioMessageChannel提供了方便的消息处理功能,可以对收到的字节流进行解码、转换成特定的消息对象,并提供了方便的事件驱动机制,方便开发者对消息进行处理和管理。
    
    例如,在自定义的RPC协议中,服务端需要解码和反序列化请求消息,调用相应的服务方法,并将响应消息转换为字节流输出。使用AbstractNioMessageChannel可以方便地处理这些消息读写操作,使用自定义的解码器和编码器可以将字节流转换为特定的消息对象,并且在ChannelHandler中实现业务逻辑,通过事件驱动机制方便地管理消息的读写和处理。
    
    综上所述,AbstractNioByteChannel适合用于处理字节流数据,适合用于客户端。而AbstractNioMessageChannel适合用于处理消息,适合用于服务端
    
  • NioSocketChannel

    NioSocketChannel是AbstractNioByteChannel的子类,NioSocketChannel封装了NIO中的SocketChannel,实现了IO的读写连接操作。Netty服务的每个连接都会生成一个NioSocketChannel对象

  • NioServerSocketChannel

    NioServerSocektChannel是AbstractNioMessageChannel的子类,一般是服务端进行使用,并且只负责监听Socket的接入,不关心IO读写。

二丶服务端启动是NioServerSocketChannel是如何实例化并注册到EventLoop中的

客户端的NioSocketChannel实例化和注册流程与服务端类似
image-20230827183358838

如上代码中,服务端指定了Channel类型,然后调用bind方法,在bind方法中会进行Channel的初始化+注册到EventLoop中

image-20230827183607939

1.NioServerSocketChannel的实例化

在不指定ChannelFactory的时候,这里默认是ReflectiveChannelFactory,如同其名称一样,ReflectiveChannelFactory会使用反射的方式构建出Channel

image-20230827184150871

随后会使用SelectorProvider#openServerSocketChannel创建出一个jdk原生的ServerSocketChannel。

然后调用父类构造器,设置Channel为非阻塞,并调用newUnsafe和newChannelPipeline实例化unsafe和channelPipeline

image-20230827184557990

对于服务端来说这里newUnsafe产生的是NioMessageUnsafe,ChannelPipeline通常使用的是DefaultChannelPipeline

2.NioServerSocketChannel的初始化

image-20230827185312380

初始化会将我们在ServerBootStrap中设置的参数设置到NioServerSocketChannel中

并向ChannelPipeline添加一个ServerBootstrapAcceptor,ServerBootstrapAcceptor和Netty的reactor模式有关,此类的作用后续进行学习。

3.NioServerSocketChannel的注册

随后会使用ServerBootStrap中的EventLoopGroup#register方法进行注册,这里的使用的EventLoopGroup是demo中指定的bossGroup

image-20230827185813543

因为在Reactor模式中,bossGroup负责处理ACCEPT事件,单线

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇微服务网关 —— SpringCloud Net.. 下一篇【教程分享】Docker搭建Zipkin,..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目