接着执行如下代码:
ChannelFuture future = serverBootstrap.bind(8088).sync();
这里是真正的启动源码的地方:这行代码做的事情太多太多太多…了
跟踪源码到AbstractBootstrap类的如下方法:
private ChannelFuture doBind(final SocketAddress localAddress) {
//初始化和注册
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
if (regFuture.isDone()) {
// At this point we know that the registration was complete and successful.
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
// IllegalStateException once we try to access the EventLoop of the Channel.
promise.setFailure(cause);
} else {
// Registration was successful, so set the correct executor to use.
// See https://github.com/netty/netty/issues/2586
promise.registered();
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
从这里开始先跟踪如下代码:
final ChannelFuture regFuture = initAndRegister();
以下代码都是该方法的内容
跟踪代码:
//初始化并注册
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
//通过反射创建NioServerSocketChannel
//channelFactory=new ReflectiveChannelFactory ---> constructor=NioServerSocketChannel.class.getConstructor();
//channel=NioServerSocketChannel
channel = channelFactory.newChannel();
init(channel);
} catch (Throwable t) {
if (channel != null) {
// channel can be null if newChannel crashed (eg SocketException("too many open files"))
channel.unsafe().closeForcibly();
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
//config().group()==bossGroup ===》 EventLoopGroup bossGroup=new NioEventLoopGroup(1);
//register开启了事件轮询线程
//config().group() boosGroup
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
这里创建了channel=NioServerSocketChannel这里为什么是这个实体可以看之前上面有说过然后看init()方法:
@Override
void init(Channel channel) throws Exception {
//channel=NioServerSocketChannel
//options0 获取的是用户自己设置的tcp参数 ServerBootstrap.option(ChannelOption.SO_BACKLOG,128)
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
//设置用户设置的tcp参数
setChannelOptions(channel, options, logger);
}
//attrs0() ServerBootstrap.attr() 获取用户设置的attr参数
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
//channel=NioServerSocketChannel
//获取AbstractChannel.pipeline();的pipeline(DefaultChannelPipeline)
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));
}
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));
}
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
//System.out.println(ch==channel); true
final ChannelPipeline pipeline = ch.pipeline();
//System.out.println(pipeline==p); true
//config.handler()=自己创建的new ChannelInitializer<ServerSocketChannel>()
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
// System.out.println("执行了");
//bossGroup将客户端连接转交给workerGroup
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}
主要看 ChannelPipeline p = channel.pipeline();这里的p有值是因为在创建NioServerSocketChannel的构造方法时赋值的.
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
//创建尾结点
tail = new TailContext(this);
//创建头节点 头节点中维护了AbstractChannel中unsafe对象
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
可以看出来该实体创建了头尾节点,且是链表的结构;
接下来看addlast()方法跟踪到如下代码;
@Override
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
//group=null
//name =null
//handler=new ChannelInitializer<Channel>
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
//检查添加
checkMultiplicity(handler);
//filterName(name, handler) 当我们没有指定名字时 给我们默认生成一个
//new DefaultChannelHandlerContext()
newCtx = newContext(group, filterName(name, handler), handler);
addLast0(newCtx);
// If the registered is false it means that the channel was not registered on an eventLoop yet.
// In this case we add the context to the pipeline and add a task that will call
// ChannelHandler.handlerAdded(...) once the channel is registered.
if (!registered) {
//判断handlerState属性等于0 并且设置为1
newCtx.setAddPending();
callHandlerCallbackLater(newCtx, true);
return this;
}
//返回NioEvenGroup
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
callHandlerAdded0(newCtx);
return this;
}
newCtx = newContext(group, filterName(name, handler), handler);完成以下事情:
给DefaultChannelHandlerContext这个类的属性附上值
//此Handler是ChannelInitializer
this.handler = handler;
addLast0(newCtx);这个就是把newCtx 这个链表的节点加入pipeline里的链表属性结构中去这样链表结构如下
head->newctx->tail
tail指向head形成闭环;
接下来走 callHandlerCallbackLater(newCtx, true);
主要是给defultpipeline类的private PendingHandlerCallback pendingHandlerCallbackHead;赋值为new PendingHandlerAddedTask(newCtx);
这个init()方法就结束了接下来继续看
abstractbootStrap的initAndRegister() 方法里的 ChannelFuture regFuture = config().group().register(channel);
跟踪到会到如下:
AbstractChannel的的内部类AbstractUnsafe的register()方法
@Override
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;
}
//promise=DefaultChannelPromise
//eventLoop=SingleThreadEventLoop
//this.eventLoop=NioEventLoop==>SingleThreadEventLoop.this
AbstractChannel.this.eventLoop = eventLoop;
//他们最终都调用了register0 eventLoop.inEventLoop()的作用?
if (eventLoop.inEventLoop()) {
register0(promise);
} else {
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
System.out.println("register0");
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);
}
}
}
根据逻辑判断接下来会走
eventLoop.execute(new Runnable() {
@Override
public void run() {
System.out.println(“register0”);
register0(promise);
}
});
继续跟踪到
SingleThreadEventExecutor的execute();
@Override
public void execute(Runnable task) {
System.out.println("ccccccccccc");
if (task == null) {
throw new NullPointerException("task");
}
//调用doStartThread方法启动事件轮询后此方法返回true
boolean inEventLoop = inEventLoop();
//将任务加入线程队列
addTask(task);
//判断当前执行此任务的线程是否是SingleThreadEventExecutor
if (!inEventLoop) {
startThread();
if (isShutdown()) {
boolean reject = false;
try {
if (removeTask(task)) {
reject = true;
}
} catch (UnsupportedOperationException e) {
// The task queue does not support removal so the best thing we can do is to just move on and
// hope we will be able to pick-up the task before its completely terminated.
// In worst case we will log on termination.
}
if (reject) {
reject();
}
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
//唤醒阻塞的selectT
wakeup(inEventLoop);
}
}
其中 addTask(task);该代码是 让
SingleThreadEventExecutor类的属性 private final Queue taskQueue;里加了一个task任务.这个任务就就只有一个方法register0()
然后走 startThread();方法跟踪下去到
SingleThreadEventExecutor的doStartThread()
private void doStartThread() {
assert thread == null;
//真正的启动线程
executor.execute(new Runnable() {
@Override
public void run() {
//将此线程保存起来
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
}
boolean success = false;
updateLastExecutionTime();
try {
SingleThreadEventExecutor.this.run();
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
for (;;) {
int oldState = state;
if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
break;
}
}
// Check if confirmShutdown() was called at the end of the loop.
if (success && gracefulShutdownStartTime == 0) {
if (logger.isErrorEnabled()) {
logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
"be called before run() implementation terminates.");
}
}
try {
// Run all remaining tasks and shutdown hooks.
for (;;) {
if (confirmShutdown()) {
break;
}
}
} finally {
try {
cleanup();
} finally {
// Lets remove all FastThreadLocals for the Thread as we are about to terminate and notify
// the future. The user may block on the future and once it unblocks the JVM may terminate
// and start unloading classes.
// See https://github.com/netty/netty/issues/6596.
FastThreadLocal.removeAll();
STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
threadLock.countDown();
if (logger.isWarnEnabled() && !taskQueue.isEmpty()) {
logger.warn("An event executor terminated with " +
"non-empty task queue (" + taskQueue.size() + ')');
}
terminationFuture.setSuccess(null);
}
}
}
}
});
}
thread = Thread.currentThread();这个代码块赋值thread属性为当前线程,
接着看下面的SingleThreadEventExecutor.this.run();的run()方法跟踪到子类nioeventloop的run方法如下:
//事件循环
@Override
protected void run() {
for (;;) {
try {
try {
//hasTasks() 若taskQueue or tailTasks任务队列中有任务 返回false 没有则返回true
// //有任务返回selectnow的返回值 没任务返回-1
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue;
case SelectStrategy.BUSY_WAIT:
// fall-through to SELECT since the busy-wait is not supported with NIO
case SelectStrategy.SELECT:
//首先轮询注册到reactor线程对应的selector上的所有的channel的IO事件
//wakenUp 表示是否应该唤醒正在阻塞的select操作,netty在每次进行新的loop之前,都会将wakeUp 被设置成false,标志新的一轮loop的开始
select(wakenUp.getAndSet(false));
if (wakenUp.get()) {
selector.wakeup();
}
// fall through
default:
}
} catch (IOException e) {
// If we receive an IOException here its because the Selector is messed up. Let's rebuild
// the selector and retry. https://github.com/netty/netty/issues/8566
rebuildSelector0();
handleLoopException(e);
continue;
}
cancelledKeys = 0;
needsToSelectAgain = false;
final int ioRatio = this.ioRatio;
if (ioRatio == 100) {
try {
processSelectedKeys();
} finally {
// Ensure we always run tasks.
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
//2.处理产生网络IO事件的channel
processSelectedKeys();
} finally {
// Ensure we always run tasks.
final long ioTime = System.nanoTime() - ioStartTime;
//3.处理任务队列
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
} catch (Throwable t) {
handleLoopException(t);
}
// Always handle shutdown even if the loop processing threw an exception.
try {
if (isShuttingDown()) {
closeAll();
if (confirmShutdown()) {
return;
}
}
} catch (Throwable t) {
handleLoopException(t);
}
}
}
以上代码根据逻辑,因为启动的时候,是没有往selector注册事件所以 switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) 这个结果为0;所以直接往下走到
//2.处理产生网络IO事件的channel
processSelectedKeys();
这个方法主要是处理通道,第一次肯定没有所以跳过到
//3.处理任务队列
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
处理taskqueue里的任务目前这队列只有一个run()就是上面register0()方法,现在开始执行该方法,该方法也是该线程在执行
AbstractChannel类的内部类的AbstractUnsafe方法;如下
private void register0(ChannelPromise promise) {
try {
// 检查通道是否仍然打开,因为它可以在寄存器的平均时间内关闭
// 调用在eventLoop之外
//promise=DefaultChannelPromise
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
//调用NioServerSocketChannel 通过反射创建出来nio底层channel的register方法 选择器看不同操作系统
doRegister();
neverRegistered = false;
registered = true;
// 确保在实际通知承诺之前调用handlerAdded(…)。这是需要的
// 用户可能已经通过ChannelFutureListener中的管道触发事件。
//会执行handlerAdded方法
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
//会执行channelRegistered
pipeline.fireChannelRegistered();
// 只有当通道从未被注册时,才激活该通道。这可以防止解雇
// 如果取消注册并重新注册通道,则多个通道将激活。
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// 这个通道之前已经注册,并设置了autoRead()。这意味着我们需要开始读取
// 这样我们就可以处理入站数据。
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// 直接关闭通道,避免FD泄漏。
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
其中的 doRegister();
//注册核心方法
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
//javaChannel() ==> ServerSocketChannel 通过反射创建出来nio底层channel
//调用Nio底层将ServerSocketChannel注册到selector上
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
//强制选择器现在选择,因为“已取消”的SelectionKey可能仍然是
//缓存并没有删除,因为还没有调用Select.select(..)操作。
eventLoop().selectNow();
selected = true;
} else {
//我们之前在选择器上强制执行了select操作,但是SelectionKey仍然缓存
//不管什么原因。JDK错误?
throw e;
}
}
}
}
是把serversocketchannel注册到netty的替换过的selector上,此时的感兴趣事件没有,且加了附加对象abstractnioChannel;
接下来看
//会执行handlerAdded方法
pipeline.invokeHandlerAddedIfNeeded();
这个方法实际上就是运行了处理链中的中间节点,该节点的属性有个handler值为ChannelInitializer实体上面的代码:
如下
p.addLast(new ChannelInitializer() {
@Override
public void initChannel(final Channel ch) throws Exception {
//System.out.println(chchannel); true
final ChannelPipeline pipeline = ch.pipeline();
//System.out.println(pipelinep); true
//config.handler()=自己创建的new ChannelInitializer()
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
// System.out.println(“执行了”);
//bossGroup将客户端连接转交给workerGroup
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
实际运行代码里的initchannel()方法.,其中的 pipeline.addLast(handler);这个handler就是我们开发的那个handler代码上
.handler(new NettyTestHendler())
此时的pipeline的handler;链表是head->newctx->nettyTestHendler->tail
接下来
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
这个又会往pipeline加个节点
此时的pipeline的handler;链表是head->newctx->nettyTestHendler->ServerBootstrapAcceptor-> tail
接下会把newctx给删除
最后服务端的serversocketChannel的pipeline的处理链为
head->nettyTestHendler->ServerBootstrapAcceptor-> tail
这样基本上初始化和注册就好了
总结:initAndRegister();这个方法主要是做了初始化服务端的处理链的构造,以及把通道注册到selector上