Netty—Channel

文章目录

  • 一、Channel 是什么?️
  • 二、 Channel 的继承体系
  • 三、Channel 的初始化过程
    • 首先,channel() 指定 ChannelFactory 类型
    • 其次,Channel 实例化

一、Channel 是什么?️

Netty 中的 Channel 可以看成网络编程中的 Socket,其提供了一系列 IO 操作的 API,比如 read、write、bind、connect 等,大大降低了直接使用 Socket 类的复杂性。同时也包含了 Netty 框架相关的一些功能,包括获取 Channel 的 EventLoop,获取缓冲区分配器 ByteBufAllocator 和 pipeline 等。

二、 Channel 的继承体系

Channel 类体系的设计与其实现功能密不可分,父类中实现的是子类共同的功能。在多层次的抽象类中,每一个层次的抽象类负责实现一种功能。

Netty—Channel_第1张图片

从上面的继承关系可以看出,NioSocketChannel 和 NioServerSocketChannel 分别对应客户端和服务端的 Channel,两者的直接父类不一致,因此对外提供的功能也是不相同的。比如当发生 read 事件时,NioServerSocketChannel 的主要逻辑就是建立新的连接,而 NioSocketChannel 则是读取传输的字节进行业务处理。

Channel 定义了 核心方法

public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
    // 返回此Channel的全局唯一标识符
    ChannelId id();
    // 返回此Channel被注册到的EventLoop
    EventLoop eventLoop();
		// 返回此Channel的父Channel,如果是ServerSocketChannel实例则返回null,而SocketChannel实例则返回创建其对应的ServerSocketChannel
    Channel parent();
		// 返回该通道的配置参数
    ChannelConfig config();
		// 如果通道是打开的并且稍后可能会激活,则返回true
    boolean isOpen();
		// 返回此Channel是否已经注册到EventLoop
    boolean isRegistered();
  	// 返回此Channel是否处于激活状态
    boolean isActive();
  	// 返回此channel的元数据
    ChannelMetadata metadata();
		// 返回此channel绑定到的本地地址。
    SocketAddress localAddress();
		// 返回连接到此channel的远程地址。
    SocketAddress remoteAddress();
		// 通道的关闭凭证,当该通道关闭时将通知它。可以同步阻塞,也可以添加执行器异步去处理
    ChannelFuture closeFuture();
		// 是否可写,如果通道的写缓冲区未满,即返回true,表示写操作可以立即 操作缓冲区,然后返回。
    boolean isWritable();
    long bytesBeforeUnwritable();
    long bytesBeforeWritable();
		// 返回 Unsafe
    Unsafe unsafe();
		// 返回 管道
    ChannelPipeline pipeline();
		// 返回 字节缓冲区分配器
    ByteBufAllocator alloc();

    @Override
    Channel read();

    @Override
    Channel flush();
	
  	
    interface Unsafe {
			// 略...
    }
}

Unsafe ——Channel 的辅助接口

此 Unsafe 非 java中的Unsafe,它可以看作是 Channel 的辅助接口,它不能被用户代码直接调用!实际的网络IO操作基本都是由 Unsafe功能类负责实现的。

Netty—Channel_第2张图片

其中 io.netty.channel.AbstractChannel.AbstractUnsafe 实现了register、bind、close等方法。其还有一个抽象类io.netty.channel.nio.AbstractNioChannel.AbstractNioUnsafe,它包含了两个常用的实现类:

  • io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe,通过以下初始化源码分析我们发现NioServerSocketChannel初始化时创建的unsafe是NioMessageUnsafe。Netty—Channel_第3张图片

  • io.netty.channel.nio.AbstractNioByteChannel.NioByteUnsafe

三、Channel 的初始化过程

下面就以 NioServerSocketChannel 为例,带大家了解下该类的初始化过程,整体流程如下:

  1. 启动引导类中通过 channel() 方法指定生成的 ChannelFactory 类型
    1. 启动引导类中通过 channel() 指定底层创建的 Channel 类型
    2. 根据指定的 Channel 类型创建出 ChannelFactory,后续通过该工厂类进行 Channel 的实例化
  2. 通过 ChannelFactory 来构造对应 Channel,并在实例化的过程中初始化了一些重要属性,比如 pipeline

首先,channel() 指定 ChannelFactory 类型

在上面的服务端启动过程中,ServerBootstrap 调用 channel() 方法并传入 NioServerSocketChannel,其底层代码逻辑为:

/**
* 用于从中创建通道实例的类。
*/
public B channel(Class<? extends C> channelClass) {
    return channelFactory(new ReflectiveChannelFactory<C>(
            ObjectUtil.checkNotNull(channelClass, "channelClass")
    ));
}
// ReflectiveChannelFactory 构建方法
public ReflectiveChannelFactory(Class<? extends T> clazz) {
    ObjectUtil.checkNotNull(clazz, "clazz");
    try {
      this.constructor = clazz.getConstructor();
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException("Class " + StringUtil.simpleClassName(clazz) +
                                         " does not have a public non-arg constructor", e);
    }
}

整体逻辑很简单,通过传入的 Class 对象指定一个 Channel 反射工厂,后续调用工厂方法获取指定类型的 Channel 对象。

其次,Channel 实例化

Netty—Channel_第4张图片

ChannelFactory 的整体逻辑就是通过反射的方式新建 Channel 对象,而 Channel 对象的类型则是在启动引导类中通过 channel() 方法进行指定的。在实例化 Channel 的过程中,会对其内部的一些属性进行初始化,而对这些属性的了解,可以使我们对 Netty 中各个组件的作用范围有一个更加清晰的理解,下面看下 NioServerSocketChannel 的构造函数源码

Netty—Channel_第5张图片
Netty—Channel_第6张图片

你可能感兴趣的:(Netty学习之旅,java,linux,服务器)