Channel-Unsafe

约 366 字大约 1 分钟

Channel-Unsafe

Unsafe 初始化

  1. Unsafe 的初始化都是在Channel初始化的时候进行初始化的,并且使用的是模版设计模式。
protected AbstractChannel(Channel parent) {
      this.parent = parent;
      id = newId();
      // 这里会进行初始化
      unsafe = newUnsafe();
      pipeline = newChannelPipeline();
}

protected abstract AbstractUnsafe newUnsafe();

AbstractNioMessageChannel

  1. NioServerSocketChannel其初始化时,newUnsafe()调用的是其父亲AbstractNioMessageChannelnewUnsafe() 方法。
public NioServerSocketChannel(ServerSocketChannel channel) {
    // 只关心 SelectionKey.OP_ACCEPT事件
    // 这里一直调用到AbstractChannel,然后AbstractChannel#newUnsafe在回调到AbstractNioMessageChannel
    super(null, channel, SelectionKey.OP_ACCEPT);
    config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}

// AbstractNioMessageChannel
protected AbstractNioUnsafe newUnsafe() {
    return new NioMessageUnsafe();
}
  1. AbstractNioMessageChannel#read()方法会在pipeline.fireChannelRead(readBuf.get(i));中使用 ServerBootstrapAcceptor 产生 NioSocketChannel

AbstractNioByteChannel

  1. NioSocketChannel其初始化时,newUnsafe()调用的是其父亲AbstractNioByteChannelnewUnsafe() 方法。
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
   // 只关心 SelectionKey.OP_READ
  // 这里一直调用到AbstractChannel,然后AbstractChannel#newUnsafe在回调到AbstractNioByteChannel
   super(parent, ch, SelectionKey.OP_READ);
}

// AbstractNioByteChannel
protected AbstractNioUnsafe newUnsafe() {
        return new NioByteUnsafe();
}
  1. NioByteUnsafe进行read()时候是进行数据处理。

为什么要拆分呢?

Split AbstractNioChannel into two subtypes
- AbstractNioMessageChannel and AbstractNioStreamChannel
- Better performance
- Replaced 'if' checks with polymorphism
  1. 从上面看AbstractNioChannel用策略+模版设计模式进行处理主要是为了性能和扩展。

TIPS

Unsafe operations that should never be called from user-code. These methods are only provided to implement the actual transport, and must be invoked from an I/O thread except for the following methods:

  • localAddress()
  • remoteAddress()
  • closeForcibly()
  • register(EventLoop, ChannelPromise)
  • deregister(ChannelPromise)
  • voidPromise()

除了上面的方法,不应该从用户代码中调用的不安全操作,这些方法仅用于实现实际传输,并且必须从 I/O 线程调用。