参考资料
先看看图
NioEventLoop的run方法
//NioEventLoop的run方法主要是用来处理绑定的Channel的所有任务的
//1.轮训处理注册的Channel的IO事件
//2.轮训处理注册的Channel的所有异步任务,也就是任务队列里的操作
//3.NioEventLoop作为Boss EventLoop处理连接事件
//3.NioEventLoop作为Worker EventLoop处理读写事件
protected void run() {
for (;;) {
//省去无用代码....
if (ioRatio == 100) {
try {
//处理Selector上Channel的事件
processSelectedKeys();
} finally {
//处理Selector上Channel的所有发生的异步任务,发生回调
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
//省去无用代码....
}
}
NioEventLoop的processSelectedKeys方法
//处理Channel的IO事件的方法
private void processSelectedKeys() {
if (selectedKeys != null) {
processSelectedKeysOptimized();
} else {
processSelectedKeysPlain(selector.selectedKeys());
}
}
//处理Channel的IO事件的方法
//1.获取到新连接Channel
//2.进一步处理新的Channel
private void processSelectedKeysOptimized() {
for (int i = 0; i < selectedKeys.size; ++i) {
final SelectionKey k = selectedKeys.keys[i];
selectedKeys.keys[i] = null;
//获取到新的channel
final Object a = k.attachment();
if (a instanceof AbstractNioChannel) {
//处理新连接
processSelectedKey(k, (AbstractNioChannel) a);
} else {
@SuppressWarnings("unchecked")
NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
processSelectedKey(k, task);
}
}
}
//处理Channel上的事件
//对于服务端类型的父类通道,只会处理连接事件(SelectionKey.OP_ACCEPT)
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
省去无用代码....
try {
int readyOps = k.readyOps();
if ((readyOps & SelectionKey.OP_WRITE) != 0) {
ch.unsafe().forceFlush();
}
//处理读事件和连接事件
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
//使用channel绑定的unsafe来操作读和连接事件
unsafe.read();
}
} catch (CancelledKeyException ignored) {
unsafe.close(unsafe.voidPromise());
}
}
NioMessageUnsafe的read方法
//处理NIO事件的类
private final class NioMessageUnsafe extends AbstractNioUnsafe {
private final List<Object> readBuf = new ArrayList<Object>();
//处理读事件方法
@Override
public void read() {
//获取Channel相关的pipeline,如果是父通道,那么里面有注册时候绑定的
//ServerBootstrapAcceptor的处理器
final ChannelPipeline pipeline = pipeline();
int size = readBuf.size();
for (int i = 0; i < size; i ++) {
readPending = false;
//开始使用通道绑定的pipeline处理新连接
pipeline.fireChannelRead(readBuf.get(i));
}
}
}
DefaultChannelPipeline的fireChannelRead方法
//Pipeline处理器链的入口,责任链模式的典型
public final ChannelPipeline fireChannelRead(Object msg) {
AbstractChannelHandlerContext.invokeChannelRead(head, msg);
return this;
}
//从Pipeline的头Hadler开始处理
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
//获取下一个Hadler
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
//不断执行下一个Hadler,这里会到我们绑定的ServerBootstrapAcceptor进行处理
next.invokeChannelRead(m);
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelRead(m);
}
});
}
}
//开始真正Hadler的处理流程
private void invokeChannelRead(Object msg) {
if (invokeHandler()) {
try {
((ChannelInboundHandler) handler()).channelRead(this, msg);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRead(msg);
}
}
ServerBootstrapAcceptor的channelRead方法
//处理新连接的真正核心方法,因为是传输类型通道,那么其实是注册到childGroup的,这个需要注意
//1.使用worker EventLoopGroup上的EventLoop进行注册新的Channel
//2.可以体会到连接和读写事件使用的 EventLoopGroup是区分了的
//3.注册新通道后,和之前注册服务端通道做的事情是一样的(注册事件不一样)
// a.将新通道绑定到相应的EventLoop上
// b.注册读写事件
// c.绑定相关自定义的处理器到Pipeline
// d.启动EventLoop线程,进行轮训处理子通道的读写事件
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
//使用worker EventLoopGroup上的EventLoop进行注册新的Channel
childGroup.register(child).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
总结
新客户端连接整个流程就是boss和worker之间如何交互,woker里面的eventLoop如何初始化,注册,也说明了worker的一个触发时机