01NioSocketChannel笔记

1.在NioSocketChannel里面直接从java的SelectorProvider里面拿到SelectorProvider
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
2.在创建NioSocketChannel的时候会创建一个, NioSocketChannel会把NioSocketChannel和socke传入
public NioSocketChannel(Channel parent, SocketChannel socket) {
super(parent, socket);
config = new NioSocketChannelConfig(this, socket.socket());
}

3.newUnsafe调用的是NioSocketChannel的newUnsafe方法,返回的是NioSocketChannelUnsafe的类
protected AbstractNioUnsafe newUnsafe() {
return new NioSocketChannelUnsafe();
}

4.newPipeline会把当前的NioSocketChannel传入进去
protected DefaultChannelPipeline newChannelPipeline() {
return new DefaultChannelPipeline(this);
}

在DefaultChannelPipeline里面会创建AbstractChannelHandlerContext 双向链表head和tail
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);

tail = new TailContext(this);
head = new HeadContext(this);

head.next = tail;
tail.prev = head;
}

head和tail里面传入的this是DefaultChannelPipeline
链表中 head 是一个 ChannelOutboundHandler, 而 tail 则是一个 ChannelInboundHandler.
接着看一下 HeadContext 的构造器:

HeadContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, HEAD_NAME, false, true);
unsafe = pipeline.channel().unsafe();
}

 

----------
第二部分是NioEventLoopGroup

1.NioEventLoop 有几个重载的构造器, 不过内容都没有什么大的区别, 最终都是调用的父类MultithreadEventLoopGroup构造器:

protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
在MultithreadEventLoopGroup里面定义

DEFAULT_EVENT_LOOP_THREADS是取cpu处理器的个数*2

private static final int DEFAULT_EVENT_LOOP_THREADS;

static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
}
}

2.在 MultithreadEventExecutorGroup里面定义EventExecutor数据 children,
EventExecutorChooserFactory.EventExecutorChooser chooser;

EventExecutorChooserFactory chooserFactory 是在
DefaultEventExecutorChooserFactory.INSTANCE 创建的
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();

public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {

private final EventExecutor[] children;
private final Set<EventExecutor> readonlyChildren;
private final AtomicInteger terminatedChildren = new AtomicInteger();
private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
private final EventExecutorChooserFactory.EventExecutorChooser chooser;

在 MultithreadEventExecutorGroup构造函数中,创建 children = EventExecutor[nThreads];
主要做了两件事,对children的每一个元素创建一个newchild
第二是chooserFactory.newChooser方法创建一个EventExecutorChooser

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {

children = new EventExecutor[nThreads];

for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
}
}

chooser = chooserFactory.newChooser(children);

final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};

for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}

Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}


3.在 chooser = chooserFactory.newChooser(children); 实现方法

public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}

4.熟悉EventExcutor之前,要知道Excutor是线程池的老祖宗
ThreadPoolExecutor用来创建线程池的,都是通过攻击类Excutors来创建的
比如
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

EventExcutor是从ScheduledExecutorService里面派生出来的接口
public interface EventExecutorGroup extends ScheduledExecutorService, Iterable<EventExecutor>

5.在 children[i] = newChild(executor, args); 的时候,调用的是NIOEventLoopGroup的newChild方法

protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}

返回的是一个NioEventLoop对象,NIOEventLoopGroup是继承了SingleThreadEventLoop的

public final class NioEventLoop extends SingleThreadEventLoop

SinleThreadEventLoop 这个单线程池是实现了EventExcutor接口,还继承了 AbstractExecutorService
public abstract class AbstractEventExecutor extends AbstractExecutorService implements EventExecutor

AbstractExecutorService 就是线程池 ThreadPoolExecutor 的父类

6.总结
最后总结一下整个 EventLoopGroup 的初始化过程吧:

EventLoopGroup(其实是MultithreadEventExecutorGroup) 内部维护一个类型为 EventExecutor children 数组, 其大小是 nThreads, 这样就构成了一个线程池

如果我们在实例化 NioEventLoopGroup 时, 如果指定线程池大小, 则 nThreads 就是指定的值, 反之是处理器核心数 * 2

MultithreadEventExecutorGroup 中会调用 newChild 抽象方法来初始化 children 数组

抽象方法 newChild 是在 NioEventLoopGroup 中实现的, 它返回一个 NioEventLoop 实例.

NioEventLoop 属性:

SelectorProvider provider 属性: NioEventLoopGroup 构造器中通过 SelectorProvider.provider() 获取一个 SelectorProvider

Selector selector 属性: NioEventLoop 构造器中通过调用通过 selector = provider.openSelector() 获取一个 selector 对象.


-----------------

第三部分 channel的初始化和注册
1.channel注册是注入到selector里面的, 在bootStrap里面调用的
final ChannelFuture initAndRegister() {
Channel channel = null;
channel = channelFactory.newChannel();
init(channel);

ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}

return regFuture;
}


2.在 ChannelFuture regFuture = config().group().register(channel);

config是BootStrap里面定义的, 然后把自己bootstrap当做参数传入进去的
private final BootstrapConfig config = new BootstrapConfig(this);

group方法就是返回的就是EventLoopGroup
public final EventLoopGroup group() {
return group;
}

register调用的是MultithreadEventLoopGroup类的,
他是NIOEventLoopGroup的父类, 你放在bootStrap里面的是NIOEventLoopGroup对象

public ChannelFuture register(Channel channel) {
return next().register(channel);
}

next方法是MultithreadEventExecutorGroup类的
public EventExecutor next() {
return chooser.next();
}

调用的是chooser的next方法, chooser是在 MultithreadEventExecutorGroup的构造函数中创建的
参数是children也就是EventExcutor数组,这个EventExcutor的实现类是NioEventLoop
NioEventLoop 是 SingleThreadEventLoop类的子类

chooser = chooserFactory.newChooser(children);

next方法最终的调用是PowerOfTwoEventExecutorChooser类或者是GenericEventExecutorChooser

PowerOfTwoEventExecutorChooser类的
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}

GenericEventExecutorChooser类的
private static final class GenericEventExecutorChooser implements EventExecutorChooser {


@Override
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}

}

每一次调用next方法,idx索引值都会自增,从0开始
register方法是在 SingleThreadEventLoop类的

public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}

DefaultChannelPromise持有两个参数对象NioEventLoop和NioSocketChannel
channel是在BootStrap里面传入进去的NioSocketChannel类创建出来的实例
this 对象是NioEventLoop
new DefaultChannelPromise(channel, this);

public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}

这个register是AbstractUnsafe的register,是从NioSocketChannel里面拿出来的
promise.channel().unsafe().register(this, promise);

public final void register(EventLoop eventLoop, final ChannelPromise promise) {
if (eventLoop == null) {
throw new NullPointerException("eventLoop");
}
if (isRegistered()) {
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
if (!isCompatible(eventLoop)) {
promise.setFailure(
new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
return;
}
//上面这些都是抛异常的方法

AbstractChannel.this.eventLoop = eventLoop;

if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
logger.warn(
"Force-closing a channel whose registration task was not accepted by an event loop: {}",
AbstractChannel.this, t);
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
}

inEventLoop是判断当前的线程是否等于SingleThreadEventExecutor类的thread
public boolean inEventLoop() {
return inEventLoop(Thread.currentThread());
}

SingleThreadEventExecutor类的
public boolean inEventLoop(Thread thread) {
return thread == this.thread;
}


3.调用register0方法
DefaultChannelPromise持有两个参数对象NioEventLoop和NioSocketChannel

register0是AbstractUnsafe这个类的,
AbstractUnsafe.register0

但是它里面调用的doRegister方法是 AbstractChannel.doRegister() 的,就是回调方法
AbstractUnsafe是AbstractChannel的内部类

private void register0(ChannelPromise promise) {
try {
// check if the channel is still open as it could be closed in the mean time when the register
// call was outside of the eventLoop
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
doRegister();
neverRegistered = false;
registered = true;

// Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the
// user may already fire events through the pipeline in the ChannelFutureListener.
pipeline.invokeHandlerAddedIfNeeded();

safeSetSuccess(promise);
pipeline.fireChannelRegistered();
// Only fire a channelActive if the channel has never been registered. This prevents firing
// multiple channel actives if the channel is deregistered and re-registered.
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// Close the channel directly to avoid FD leak.
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}

调用NioSocketChannel类的doRegister方法,这个是在他的父类 AbstractNioChannel
eventLoop()返回的是NioEventLoop对象,这个是在register方法里面注册的
AbstractChannel.this.eventLoop = eventLoop;

protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.
eventLoop().selectNow();
selected = true;
} else {
// We forced a select operation on the selector before but the SelectionKey is still cached
// for whatever reason. JDK bug ?
throw e;
}
}
}
}

javachannel是在创建NioSocketChannel的时候创建的SocketChannel
EventLoop().unwrappedSelector()从NioEventLoop里面,就是EventExcutor数组里面
也就是线程池里面取出selector
0是对任务事件都不感兴趣
this把NioSocketChannel当做附件
javaChannel().register(eventLoop().unwrappedSelector(), 0, this);


总结:
我们总结一下 Channel 的注册过程:

首先在 AbstractBootstrap.initAndRegister中, 通过 group().register(channel), 调用 MultithreadEventLoopGroup.register 方法

在MultithreadEventLoopGroup.register 中, 通过 next() 获取一个可用的 SingleThreadEventLoop, 然后调用它的 register

在 SingleThreadEventLoop.register 中, 通过 channel.unsafe().register(this, promise) 来获取 channel 的 unsafe() 底层操作对象, 然后调用它的 register.

在 AbstractUnsafe.register 方法中, 调用 register0 方法注册 Channel

在 AbstractUnsafe.register0 中, 调用 AbstractNioChannel.doRegister 方法

AbstractNioChannel.doRegister 方法通过 javaChannel().register(eventLoop().selector, 0, this) 将 Channel 对应的 Java NIO SockerChannel 注册到一个 eventLoop 的 Selector 中, 并且将当前 Channel 作为 attachment.

总的来说, Channel 注册过程所做的工作就是将 Channel 与对应的 EventLoop 关联,
因此这也体现了, 在 Netty 中, 每个 Channel 都会关联一个特定的 EventLoop,
并且这个 Channel 中的所有 IO 操作都是在这个 EventLoop 中执行的; 当关联好 Channel 和 EventLoop 后,
会继续调用底层的 Java NIO SocketChannel 的 register 方法, 将底层的 Java NIO SocketChannel 注册到指定的 selector 中.
通过这两步, 就完成了 Netty Channel 的注册过程.

--------

 

转载于:https://www.cnblogs.com/handsome1013/p/10002835.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值