NioEventLoop是通用的,针对不同的事件通过attachment中的channel自动区分操作。
监听的channel为NioServerSocketChannel对应的unsafe为NioMessageUnsafe
通讯的channel为NioSocketChannel对应的unsafe为NioByteUnsafe
比如:监听的channel为NioServerSocketChannel里面的unsafe为NioMessageUnsafe里面是用于收到连接对应的read函数。
一个NioSocketChannel对应一个新的DefaultChannelPipeline,DefaultChannelPipeline不共用,
每次客户端连接都会调用ChannelInitializer中的initChannel函数用于初始化DefaultChannelPipeline中的ChannelHandlerContext链,
调用addLast时会将ChannelHandler包装成ChannelHandlerContext,name一样不允许多次添加,只要name不一样同一类handler可以添加多次
ChannelHandlerContext中有一个handler就是addLast添加的ChannelHandler,ChannelHandlerContext中有prev和next用于将
DefaultChannelPipeline中所有的ChannelHandlerContext串联起来。
ChannelHandlerContext是inbound和outbound类型之分,通过addLast添加通过instanceof区分
bind在main线程中注册,在boss线程中完成真正的bind
main线程中bind(封装bind task放入bossgroup的任务队列中)
AbstractBootstrap.doBind(SocketAddress localAddress) -- main线程中执行
{
1. ChannelFuture regFuture = initAndRegister();
{
1. channel = channelFactory.newChannel(); --NioServerSocketChannel<-->DefaultChannelPipeline
2. p.addLast(new ChannelInitializer<Channel>() { // NioServerSocketChannel 的 DefaultChannelPipeline中添加ChannelInitializer
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler(); // config: ServerBootstrapConfig
if (handler != null) {
pipeline.addLast(handler); // 这里添加的是 .handler(new LoggingHandler(LogLevel.INFO)) 中的 LoggingHandler
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor( // 用于做实际acceptor
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
3. ChannelFuture regFuture = config().group().register(channel); // 将listen的channel注册到bossgroup, 会打印 REGISTERED
4. doBind0(regFuture, channel, localAddress, promise)
{
// 注意:这里还是main线程
channel.eventLoop().execute(new Runnable() {
public void run() { // 注意:这个最终会运行在bossgroup线程中由NioEventLoop.runAllTasks中运行 【1】
if (regFuture.isSuccess()) {
channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); // 会打印 BIND: 0.0.0.0/0.0.0.0:8007
} else {
promise.setFailure(regFuture.cause());
}
}
});
}
}
}
bossgourp线程中bind
入口在【1】
AbstractChannel - pipeline.bind(localAddress, promise);
{
DefaultChannelPipeline - tail.bind(localAddress, promise);
{
DefaultChannelPipeline$TailContext
{
最终会调用到HeadContext中的bind
}
}
}
accept网络事件在boss线程中完成包装成task放入worker线程中的task列表中最终由worker线程
在channelRead中 headcontext---->bootstrapcontext中的handler创建的
ctx(logger)->ServerBootstrap$ServerBootstrapAcceptor.channelRead(ChannelHandlerContext, Object)
ServerBootstrapAcceptor - channelRead 运行在bossgroup
{
public void channelRead(ChannelHandlerContext ctx, Object msg) {
final Channel child = (Channel) msg;
child.pipeline().addLast(childHandler); // 这个为ServerBootstrap指定的childHandler(ChannelInitializer)用于初始化通讯channel中的pipe
// 注意因为用于通讯的niosocketchannle对应的pipeline中registered标志位false
这个会执行callHandlerCallbackLater(newCtx, true); 用于第在worker线程中执行register0函数时会通过pendingHandlerCallbackHead
做一些初始化工作
{
PendingHandlerCallback task = added ? new PendingHandlerAddedTask(ctx) : new PendingHandlerRemovedTask(ctx);
PendingHandlerCallback pending = pendingHandlerCallbackHead;
if (pending == null) {
pendingHandlerCallbackHead = task;
} else {
// Find the tail of the linked-list.
while (pending.next != null) {
pending = pending.next;
}
pending.next = task;
}
}
setChannelOptions(child, childOptions, logger);
for (Entry<AttributeKey<?>, Object> e: childAttrs) {
child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
}
try {
childGroup.register(child).addListener(new ChannelFutureListener() { // 用于将新建的用于通讯的 socketchannel 注册到 childGroup 中
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
forceClose(child, future.cause());
}
}
});
} catch (Throwable t) {
forceClose(child, t);
}
}
}
boss线程执行其中register函数(封装task放入workerEventLoop中的任务队列中):
1. next().register(channel);
{
register(new DefaultChannelPromise(channel, this));
{
NioEventLoop(SingleThreadEventLoop).register(Channel) line: 74
promise.channel().unsafe().register(this, promise);
{
NioSocketChannel$NioSocketChannelUnsafe(AbstractChannel$AbstractUnsafe).register(EventLoop, ChannelPromise) line: 460
{
注意:eventLoop=worker线程,因为这个运行的是boss线程,所以eventLoop.inEventLoop()为false
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() { 注意:eventLoop为worker线程,最后有worker通过task的方式调用register0
@Override
public void run() {
register0(promise); 【1】
}
});
} 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);
}
}
}
}
}
}
worker线程执行【1】包装的task run 中的 register0
private void register0(ChannelPromise promise)
{
1. doRegister();
{
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this); 最终调用 NIO的register函数,其中this为niosocketchannel
}
2. pipeline.invokeHandlerAddedIfNeeded();
{
if (firstRegistration) {
firstRegistration = false;
// We are now registered to the EventLoop. It's time to call the callbacks for the ChannelHandlers,
// that were added before the registration was done.
callHandlerAddedForAllHandlers();
{
DefaultChannelPipeline.callHandlerAddedForAllHandlers() line: 1132 中
PendingHandlerCallback task = pendingHandlerCallbackHead;
while (task != null) {
task.execute();
{
if (executor.inEventLoop()) {
callHandlerAdded0(ctx); ------- 这里会执行childHandler挂的handlerInit
{
DefaultChannelPipeline.callHandlerAdded0(AbstractChannelHandlerContext) line: 606
ctx.handler().handlerAdded(ctx);
{
EchoServer$1(ChannelInitializer<C>).handlerAdded(ChannelHandlerContext) line: 105 内部ChannelInitializer类
initChannel(ctx);
{
if (initMap.putIfAbsent(ctx, Boolean.TRUE) == null) { // Guard against re-entrance.
try {
initChannel((C) ctx.channel()); // 调用在bootstrap中的内部ChannelInitializer类中的initChannel函数
} catch (Throwable cause) {
// Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...).
// We do so to prevent multiple calls to initChannel(...).
exceptionCaught(ctx, cause);
} finally {
remove(ctx); //将内部ChannelInitializer类自己删除
}
return true;
}
return false;
}
}
}
}
}
task = task.next;
}
}
}
}
}
添加ChannelHandler逻辑
ChannelPipeline addLast(ChannelHandler... handlers)
{
DefaultChannelPipeline.addLast(EventExecutorGroup, String, ChannelHandler) line: 210
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler)
{
1. newCtx = newContext(group, filterName(name, handler), handler); --filterName会过滤名字相同的,如果name为null会调用generateName
{
1. new DefaultChannelHandlerContext(this, childExecutor(group), name, handler);
{
1. super(pipeline, executor, name, isInbound(handler), isOutbound(handler)); 这里通过instanceof自动判断isInbound和isOutbound
2. this.handler = handler; 这里很重要,后续ChannelHandlerContext对应中的handler就是handler实际用于处理的逻辑代码
}
}
2. addLast0(newCtx); 将新建的AbstractChannelHandlerContext放入到ChannelHandlerContext链中
}
}
ChannelHandler链遍历调用过程:
DefaultChannelPipeline.fireChannelRead(Object) line: 935
{
AbstractChannelHandlerContext.invokeChannelRead(ctx, msg)
{
ctx.invokeChannelRead(m) 【1】
{
((ChannelInboundHandler) handler()).channelRead(this, msg)
{
1. DefaultChannelPipeline$HeadContext.channelRead(ChannelHandlerContext, Object) line: 1359
{
ctx.fireChannelRead(msg)
{
AbstractChannelHandlerContext.invokeChannelRead(findContextInbound(), msg); 注意 findContextInbound 、
到这里查询到下一个ctx继续执行 【1】这样完成整个pipeline
}
}
}
}
}
}
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound); 判断标志
return ctx;
}