netty应用退出

netty程序,使用shutdownGracefully退出。退出前会把队列中的消息发送完,释放channel,多路复用器的去注册,清空定时器任务等。

    public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
        EventExecutor[] var6 = this.children;
        int var7 = var6.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            EventExecutor l = var6[var8];
            l.shutdownGracefully(quietPeriod, timeout, unit);
        }

        return this.terminationFuture();
    }

shutdownGracefully实现在NioEventLoop的父类SingleThreadEventExecutor中,

首先是改变state,为了防止并发问题,这里是netty 4,采用的原子类自旋的方式避免加锁。

public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
        ObjectUtil.checkPositiveOrZero(quietPeriod, "quietPeriod");
        if(timeout < quietPeriod) {
            throw new IllegalArgumentException("timeout: " + timeout + " (expected >= quietPeriod (" + quietPeriod + "))");
        } else {
            ObjectUtil.checkNotNull(unit, "unit");
            if(this.isShuttingDown()) {
                return this.terminationFuture();
            } else {
                boolean inEventLoop = this.inEventLoop();

                boolean wakeup;
                int oldState;
                int newState;
                do {
                    if(this.isShuttingDown()) {
                        return this.terminationFuture();
                    }

                    wakeup = true;
                    oldState = this.state;
                    if(inEventLoop) {
                        newState = 3;
                    } else {
                        switch(oldState) {
                        case 1:
                        case 2:
                            newState = 3;
                            break;
                        default:
                            newState = oldState;
                            wakeup = false;
                        }
                    }
                } while(!STATE_UPDATER.compareAndSet(this, oldState, newState));

                this.gracefulShutdownQuietPeriod = unit.toNanos(quietPeriod);
                this.gracefulShutdownTimeout = unit.toNanos(timeout);
                if(this.ensureThreadStarted(oldState)) {
                    return this.terminationFuture;
                } else {
                    if(wakeup) {
                        this.taskQueue.offer(WAKEUP_TASK);
                        if(!this.addTaskWakesUp) {
                            this.wakeup(inEventLoop);
                        }
                    }

                    return this.terminationFuture();
                }
            }
        }
    }

唤醒selector,由NioEventLoop实现。

 protected void wakeup(boolean inEventLoop) {
        if(!inEventLoop && this.nextWakeupNanos.getAndSet(-1L) != -1L) {
            this.selector.wakeup();
        }

    }

状态改变之后, run方法中检测到状态变化,执行closeAll方法

if(this.isShuttingDown()) {
                        this.closeAll();
                        if(this.confirmShutdown()) {
                            return;
                        }
                    }

获取channel,如果是nioChannel,则调用unsafe的close方法。

 private void closeAll() {
        this.selectAgain();
        Set<SelectionKey> keys = this.selector.keys();
        Collection<AbstractNioChannel> channels = new ArrayList(keys.size());
        Iterator var3 = keys.iterator();

        while(var3.hasNext()) {
            SelectionKey k = (SelectionKey)var3.next();
            Object a = k.attachment();
            if(a instanceof AbstractNioChannel) {
                channels.add((AbstractNioChannel)a);
            } else {
                k.cancel();
                NioTask<SelectableChannel> task = (NioTask)a;
                invokeChannelUnregistered(task, k, (Throwable)null);
            }
        }

        var3 = channels.iterator();

        while(var3.hasNext()) {
            AbstractNioChannel ch = (AbstractNioChannel)var3.next();
            ch.unsafe().close(ch.unsafe().voidPromise());
        }

    }

AbstractChannel中的内部类AbstractUnsafe的close和voidPromise方法

public final void close(ChannelPromise promise) {
            this.assertEventLoop();
            ClosedChannelException closedChannelException = new ClosedChannelException();
            this.close(promise, closedChannelException, closedChannelException, false);
        }
 public final ChannelPromise voidPromise() {
            this.assertEventLoop();
            return AbstractChannel.this.unsafeVoidPromise;
        }

判断当前链路中是否有未发送的消息,如果有则稍后再取消注册,将任务放到task中。
关闭链路

private void close(final ChannelPromise promise, final Throwable cause, final ClosedChannelException closeCause, final boolean notify) {
            if(promise.setUncancellable()) {
                if(AbstractChannel.this.closeInitiated) {
                    if(AbstractChannel.this.closeFuture.isDone()) {
                        this.safeSetSuccess(promise);
                    } else if(!(promise instanceof VoidChannelPromise)) {
                        AbstractChannel.this.closeFuture.addListener(new ChannelFutureListener() {
                            public void operationComplete(ChannelFuture future) throws Exception {
                                promise.setSuccess();
                            }
                        });
                    }

                } else {
                    AbstractChannel.this.closeInitiated = true;
                    final boolean wasActive = AbstractChannel.this.isActive();
                    final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
                    //清空发送队列
                    this.outboundBuffer = null;
                    Executor closeExecutor = this.prepareToClose();
                    if(closeExecutor != null) {
                        closeExecutor.execute(new Runnable() {
                            public void run() {
                                try {
                                    AbstractUnsafe.this.doClose0(promise);
                                } finally {
                                    AbstractUnsafe.this.invokeLater(new Runnable() {
                                        public void run() {
                                            if(outboundBuffer != null) {
                                                outboundBuffer.failFlushed(cause, notify);
                                                outboundBuffer.close(closeCause);
                                            }

                                            AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
                                        }
                                    });
                                }

                            }
                        });
                    } else {
                        try {
                            this.doClose0(promise);
                        } finally {
                            if(outboundBuffer != null) {
                                outboundBuffer.failFlushed(cause, notify);
                                outboundBuffer.close(closeCause);
                            }

                        }

                        if(this.inFlush0) {
                            this.invokeLater(new Runnable() {
                                public void run() {
                                    AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
                                }
                            });
                        } else {
                        //触发链路关闭通知事件,从多路复用器取消selectionKey
                            this.fireChannelInactiveAndDeregister(wasActive);
                        }
                    }

                }
            }
        }

从多路复用器取消selectionKey

 protected void doDeregister() throws Exception {
        this.eventLoop().cancel(this.selectionKey());
    }

关闭链路之后

protected boolean confirmShutdown() {
        if(!this.isShuttingDown()) {
            return false;
        } else if(!this.inEventLoop()) {
            throw new IllegalStateException("must be invoked from an event loop");
        } else {
            this.cancelScheduledTasks();
            if(this.gracefulShutdownStartTime == 0L) {
                this.gracefulShutdownStartTime = ScheduledFutureTask.nanoTime();
            }

            if(!this.runAllTasks() && !this.runShutdownHooks()) {
                long nanoTime = ScheduledFutureTask.nanoTime();
                if(!this.isShutdown() && nanoTime - this.gracefulShutdownStartTime <= this.gracefulShutdownTimeout) {
                
                    if(nanoTime - this.lastExecutionTime <= this.gracefulShutdownQuietPeriod) {//若没有达到指定时间,则先不退出
                        this.taskQueue.offer(WAKEUP_TASK);

                        try {
                            Thread.sleep(100L);
                        } catch (InterruptedException var4) {
                            ;
                        }

                        return false;
                    } else {
                        return true;
                    }
                } else {
                    return true;
                }
            } else if(this.isShutdown()) {
                return true;
            } else if(this.gracefulShutdownQuietPeriod == 0L) {
                return true;
            } else {
                this.taskQueue.offer(WAKEUP_TASK);
                return false;
            }
        }
    }

执行尚在taskQueue中的任务,

 do {
 //    PriorityQueue<ScheduledFutureTask<?>> scheduledTaskQueue;
            fetchedAll = this.fetchFromScheduledTaskQueue();//取出队列scheduledTaskQueue中所有的任务,放到taskQueue中。
            if(this.runAllTasksFrom(this.taskQueue)) {
                ranAtLeastOne = true;
            }
        } while(!fetchedAll);

执行taskQueue中的所有任务

//Queue<Runnable> taskQueue
protected final boolean runAllTasksFrom(Queue<Runnable> taskQueue) {
        Runnable task = pollTaskFrom(taskQueue);
        if(task == null) {
            return false;
        } else {
            do {
                safeExecute(task);
                task = pollTaskFrom(taskQueue);
            } while(task != null);

            return true;
        }
    }

执行注册到nioeventLoop中的任务

private boolean runShutdownHooks() {
        boolean ran = false;

        while(!this.shutdownHooks.isEmpty()) {
            List<Runnable> copy = new ArrayList(this.shutdownHooks);
            this.shutdownHooks.clear();
            Iterator var3 = copy.iterator();

            while(var3.hasNext()) {
                Runnable task = (Runnable)var3.next();

                try {
                    task.run();
                } catch (Throwable var9) {
                    logger.warn("Shutdown hook raised an exception.", var9);
                } finally {
                    ran = true;
                }
            }
        }

        if(ran) {
            this.lastExecutionTime = ScheduledFutureTask.nanoTime();
        }

        return ran;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值