netty源码探索

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;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值