"netty4.x" Netty Source analysis Nioeventloop (vi)

Source: Internet
Author: User
Tags data structures throwable

Inheritance Relationship:
Initialization of Nioeventloop

Nioeventloop (nioeventloopgroup parent, Threadfactory threadfactory, Selectorprovider selectorprovider) {
    super ( Parent, threadfactory, false);
    if (Selectorprovider = = null) {
        throw new NullPointerException ("Selectorprovider");
    }
    Provider = Selectorprovider;
    selector = Openselector ();
}

1, call the parent class method constructs a taskqueue, it is a linkedblockingqueue

2,openselector (): Netty is based on NIO to achieve, so also inseparable from selector.

3,disable_keyset_optimization: to determine whether the need for Sun.nio.ch.SelectorImpl in the Selectedkeys to optimize, do not configure the default need to optimize.

4, where is the main optimization: Netty The Selectedkeyset with the two field in Sun.nio.ch.SelectorImpl by reflection Selectedkeys and Publicselectedkeys bindings, you know Selectorimpl the original selectedkeys and Publicselectedkeys data structures are hashset, and HashSet's data structure is the array + linked list, the new data structure is composed of 2 arrays A, B, the initial size is 1024, avoid the performance problems caused by hashset expansion. In addition to the expansion, traversal efficiency is also a reason, for the need to traverse all elements of selectedkeys, the efficiency of the array is undoubtedly the highest.

Private Selector Openselector () {final Selector Selector;
    try {selector = Provider.openselector ();
    catch (IOException e) {throw new Channelexception ("Failed to open a new selector", e);
    } if (disable_keyset_optimization) {return selector;

        try {selectedselectionkeyset selectedkeyset = new Selectedselectionkeyset (); class<?> Selectorimplclass = Class.forName ("Sun.nio.ch.SelectorImpl", False, Platformdependent.getsy

        Stemclassloader ());
        Ensure the current selector implementation is what we can instrument.
        if (!selectorimplclass.isassignablefrom (Selector.getclass ())) {return selector;
        Field Selectedkeysfield = Selectorimplclass.getdeclaredfield ("Selectedkeys");

        Field Publicselectedkeysfield = Selectorimplclass.getdeclaredfield ("Publicselectedkeys");
        Selectedkeysfield.setaccessible (TRUE); Publicselectedkeysfield.setaCcessible (TRUE);
        Selectedkeysfield.set (selector, selectedkeyset);

        Publicselectedkeysfield.set (selector, selectedkeyset);
        Selectedkeys = Selectedkeyset;
    Logger.trace ("instrumented a optimized Java.util.Set into: {}", selector);
        catch (Throwable t) {selectedkeys = null;
    Logger.trace ("Failed to instrument a optimized java.util.Set into: {}", selector, T);
return selector; }
start of the Nioeventloop

In the last time, Nioeventloop maintains a thread that invokes the Nioeventloop run method when the thread starts, and the loop loops through a process: Select-> processselectedkeys (IO Task)-> Runalltasks (non-IO Task)

I/O tasks: ready events in Selectionkey, such as accept, connect, read, write, etc.

Non-IO tasks: tasks added to Taskqueue, such as bind, channelactive, etc.

@Override protected void Run () {for (;;)
        {Boolean oldwakenup = Wakenup.getandset (false);
            try {//To determine if there is a non-IO task, if there is any immediate return if (Hastasks ()) {Selectnow ();

                else {select (Oldwakenup);
                if (Wakenup.get ()) {selector.wakeup ();
            } cancelledkeys = 0;
            Needstoselectagain = false;
            Final int ioratio = This.ioratio;
                if (Ioratio = =) {//IO task Processselectedkeys ();
            Non-IO task runalltasks ();
                else {//the elapsed time to control the IO task and the non-IO task is longer than the final long iostarttime = System.nanotime ();

                Io task Processselectedkeys ();
                Final Long iotime = System.nanotime ()-iostarttime;
         Non-IO task runalltasks (iotime * (100-ioratio)/ioratio);   } if (Isshuttingdown ()) {CloseAll ();
                if (Confirmshutdown ()) {break; (Throwable t) {//Prevent possible consecutive immediate failures ' lead T
            O//excessive CPU consumption.
            try {thread.sleep (1000);
            catch (Interruptedexception e) {//Ignore. }
        }
    }
}

1.wakenup: used to decide whether to call Selector.wakeup (), only if Wakenup is not true, to reduce wake-up load because selector.wakeup () is an expensive operation.

2,hastask (): to determine whether there is a non-IO task, if any, choose to call Non-blocking Selectnow () Let select immediately return, otherwise the blocking way to call Select.timeoutmillis is blocked time

3,ioratio: Control the execution time of two tasks, you can limit the execution time of the non-IO task, the default value is 50, to allow the non-IO task to obtain and IO task the same execution time, this value according to their specific scenario to set.

4,Processselectedkeys (): Handling IO Events

5,runalltasks (): processing non-IO tasks

6,Isshuttingdown (): Check whether the state is marked as St_shutting_down

private void Select (Boolean oldwakenup) throws IOException {Selector Selector = this.selector;
            try {int selectcnt = 0;
            Long Currenttimenanos = System.nanotime ();
            Long Selectdeadlinenanos = Currenttimenanos + Delaynanos (Currenttimenanos); for (;;)
                {Long Timeoutmillis = (Selectdeadlinenanos-currenttimenanos + 500000L)/1000000L;
                        if (timeoutmillis <= 0) {if (selectcnt = = 0) {selector.selectnow ();
                    selectcnt = 1;
                } break;
                int selectedkeys = Selector.select (Timeoutmillis);

                Selectcnt + +; if (selectedkeys!= 0 | | oldwakenup | | wakenup.get () | | hastasks () | | hasscheduledtasks ()) {//-Sele CTED something,//-Waken up by user, or//-the task queue has a PEnding task.
                -A scheduled task is ready to processing break; } if (thread.interrupted ()) {//Thread is interrupted so reset selected keys and BRE
                    AK so we don't run into a busy loop. As is most likely a bug in the handler of the user or it ' s client library we'll//also log
                    It. https://github.com/netty/netty/issues/2426 if (logger.isdebugenabled ())
                                {Logger.debug ("selector.select () returned prematurely because" + "Thread.CurrentThread (). Interrupt () was called.
                    Use "+" nioeventloop.shutdowngracefully () to shutdown the Nioeventloop. ");
                    } selectcnt = 1;
                Break
    Long time = System.nanotime ();            if (Time-timeunit.milliseconds.tonanos (timeoutmillis) >= Currenttimenanos) {//Timeo
                    Utmillis elapsed without anything selected.
                selectcnt = 1; else if (Selector_auto_rebuild_threshold > 0 && selectcnt >= selector_auto_rebuild
                    _threshold) {//The selector returned prematurely many times in a row.
                    Rebuild the selector to work around the problem. Logger.warn ("Selector.select () returned prematurely {} times in a row;

                    Rebuilding selector. ", selectcnt);
                    Rebuildselector ();

                    selector = This.selector;
                    Select again to populate Selectedkeys.
                    Selector.selectnow ();
                    selectcnt = 1;
                Break
 } Currenttimenanos = time;           } if (Selectcnt > Min_premature_selector_returns) {if (logger.isdebugenabled ()
                {Logger.debug ("selector.select () returned prematurely {} times in a row.", selectCnt-1);
                The catch (Cancelledkeyexception e) {if (logger.isdebugenabled ()) {
            Logger.debug (CancelledKeyException.class.getSimpleName () + "raised by a selector-jdk bug?", e); }
        }
    }
Protected long Delaynanos (long Currenttimenanos) {
    scheduledfuturetask<?> scheduledtask = Peekscheduledtask ();
    if (Scheduledtask = = null) {return
        schedule_purge_interval;
    }

    Return Scheduledtask.delaynanos (Currenttimenanos);
}

Public long Delaynanos (long Currenttimenanos) {return
    Math.max (0, Deadlinenanos ()-(Currenttimenanos-start_time) );
}

Public long Deadlinenanos () {return
    Deadlinenanos;
}

1,Delaynanos (Currenttimenanos): in the parent class Singlethreadeventexecutor has a delay in the execution of the task queue, Delaynanos is going to this delay queue to see if a non-IO task is not performed
* If not, return for 1 seconds.
* If there is a task in the delay queue and the resulting calculated time (Selectdeadlinenanos-currenttimenanos) is less than 500000L nanoseconds, call Selectnow () to return directly, and vice versa to execute a blocked select

2. Select will return immediately if you encounter the following conditions

if (selectedkeys!= 0 | | oldwakenup | | wakenup.get () | | hastasks () | | hasscheduledtasks ()) {
                    //-Selected something,< c1/>//-Waken up by user, or
                    //-The task queue has a pending task.
                    -A scheduled task is ready to processing break
                    ;
                
Selected something if Select to a Ready connection (Selectedkeys > 0) waken up by user wakes the task queue has a pending task. The task queue came up with a new Tasks a scheduled task is ready for processing delay queue There is an appointment task that needs to be executed at expiration

3.selectcnt: record Select idling times (SELECTCNT), which solves the cpu100% bug caused by the notorious selector Select method in NiO, when the number of idling times exceeds 512 (defines a threshold , this threshold is 512 and can be passed in by setting system Properties Io.netty.selectorAutoRebuildThreshold in the application layer, Netty will reconstruct the new selector, The old selector on the channel transferred to the new selector, close the old selector, replace the old selector with the new selector. See the following Rebuildselector () method in detail

4,rebuildselector (): is above said.

public void Rebuildselector () {if (!ineventloop ()) {Execute (new Runnable () {@Override
            public void Run () {rebuildselector ();
        }
        });
    Return
    Final Selector oldselector = Selector;

    Final Selector Newselector;
    if (Oldselector = = null) {return;
    try {newselector = Openselector ();
        catch (Exception e) {Logger.warn ("Failed to create a new Selector.", e);
    Return
    }//Register all channels to the new Selector.
    int nchannels = 0; for (;;)
                {try {for (Selectionkey Key:oldSelector.keys ()) {Object a = key.attachment ();
                        try {if (!key.isvalid () | | Key.channel (). Keyfor (newselector)!= null) {
                    Continue
                    int interestops = Key.interestops ();
                    Key.cancel (); SElectionkey NewKey = Key.channel (). Register (Newselector, Interestops, a); if (a instanceof Abstractniochannel) {//Update Selectionkey (Abstractni
                    Ochannel) a). Selectionkey = NewKey;
                } nchannels + +;
                    catch (Exception e) {Logger.warn ("Failed to re-register a Channel to the new Selector.", e);  if (a instanceof abstractniochannel) {Abstractniochannel ch = (Abstractniochannel)
                        A
                    Ch.unsafe (). Close (Ch.unsafe (). Voidpromise ()); else {@SuppressWarnings ("unchecked") niotask<selectablechannel> t
                        Ask = (niotask<selectablechannel>) A;
                    Invokechannelunregistered (Task, key, E);
catch (Concurrentmodificationexception e) {            Probably due to concurrent modification of the key set.
        Continue
    } break;

    } selector = Newselector; try {//selector as everything else is registered to the new one oldselector.close (
    ); The catch (Throwable t) {if (logger.iswarnenabled ()) {Logger.warn ("Failed to close") {"Selector."
        , t); } logger.info ("migrated" + Nchannels + "channel (s) to the new Selector.");}

Author: Little Donkey, a game man
Dream: World Peace
GitHub Home: https://liulongling.github.io/
Csdn Home: http://blog.csdn.net/     Liulongling
If there is a mistake, please forgive and welcome the criticism.
This blog does not indicate reproduced articles to the author of all the Small donkey, welcomed the reprint, but without the consent of the author must retain this paragraph of the statement, and in the article page obvious location to the original connection, otherwise retain the right to pursue legal responsibility.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.