Analysis of the principle of NiO and preliminary----on Netty High Performance server development (i)

Source: Internet
Author: User

In addition to the special note, this site all the articles are original, reproduced please specify the address

In Bo's not long work experience, NIO does not use much, because the use of native Java NiO programming complexity, most of the time we will choose Netty,mina and other open source framework, but understand the principle of NIO is not important? On the contrary, understanding the underlying mechanism of NIO is the basis for understanding all this, so I summarize the notes that I learned when I was studying NIO so that I could review them later.

Here's what I understand about the general process of Java native NIO development:

It is roughly described as a service-side NIO operation.

The first step is to bind the port of a service

This is similar to ServerSocket in traditional blocking Io, nothing to say

The second step is to open the Channel Manager selector and register an event on selector

When a registered event occurs, Selector.select () returns or is blocked. This is a very interesting step, and also the first of the NIO is different from the traditional IO, nio through a selector thread can manage a large number of client connections, whereas traditional IO a client connection must create a new thread to serve it (of course you can use the connection pool), We know that threads are a very valuable resource to the server, a server-side process has a limited number of threads, and each thread consumes a certain amount of memory, and too many threads can cause memory overruns, in which case you might want to tune the virtual machine, For example, by modifying the parameter-XSS limit the size of a single thread, but this can lead to StackOverflow, in addition, thread scheduling needs to switch context, for the operating system, it needs to pass the TCB (thread control block) to the thread scheduling, excessive context switching wasted CPU time, Reduced system efficiency.

The third step, round-robin access selector, when the registered event arrives, the method returns

The following code can see that the method as a whole is a dead loop, polling the access selector, and the method returns when some of the events that have been registered on the selector occur. The events that occur can be obtained through Selector.selectedkeys,

This method returns a generic collection Set<selectionkey>, and traversing this collection is no different from traversing a normal collection, where we iterate through iterators because we need to delete the key that has already been processed and avoid repeating it:

 Public voidListen ()throwsIOException {//Polling Access Selector         while(true) {            //when the registered event arrives, the method returns; otherwise, the method will always blockSelector.select (); //gets the iterator for the selected item in the selector, the selected item is the registered eventiterator<?> ite = This. Selector.selectedkeys (). iterator ();  while(Ite.hasnext ()) {Selectionkey key=(Selectionkey) ite.next (); //Remove the selected key to prevent duplicate processingIte.remove ();            Here we can write our own processing logic handle (key); }        }}

In the second step, the Accept event has been registered on selector, and when Selector.select () returns here, the client is already connected, and the event can be handled in the handle method:

 Public void throws IOException {    //  Client Request Connection Event    if  (key.isacceptable ()) {
From the key can be easily taken to register the channel of this event

Serversocketchannel Server = (Serversocketchannel) key.channel ();
Get the channel to connect with the client
Socketchannel channel = Server.accept ();
Set as non-blocking
Channel.configureblocking (FALSE);

Logger.info ("The client is already connected! ");

Client connections register read events on Channel manager selector

Channel.register (This.selector, Selectionkey.op_read);

    }}

The above code is very simple, we get to register its channel through key, here is Serversocketchannel, through server.accept () to get the client connection, here can also analogy to the traditional blocking

Io, in blocking IO we can get to the socket via serversocket.accept, the only difference is that the accept method in blocking Io is blocking operation, and NiO is non-blocking.

Of course, simply connecting to the client is not useful, and the server needs to have the ability to read and write data, such as using NIO to implement an HTTP (and of course, best practice use Netty frameworks). So we need to be in selector.

Registers read events, and similarly, executes our own business logic when a read event occurs. The following is the modified code:

 Public voidHandle (Selectionkey key)throwsIOException {if(Key.isacceptable ()) {Serversocketchannel Server=(Serversocketchannel) Key.channel (); Socketchannel Channel=server.accept (); Channel.configureblocking (false); Logger.info ("The client is already connected!" "); Channel.register ( This. Selector, selectionkey.op_read); } Else if(Key.isreadable ()) {Socketchannel channel=(Socketchannel) Key.channel (); //Create Read bufferBytebuffer buffer = bytebuffer.allocate (1024); //read into buffer        intRead =channel.read (buffer); if(Read > 0){            byte[] data =Buffer.array (); String msg=NewString (data). Trim (); Logger.info ("Receive msg: {}", msg)//Write back DataBytebuffer Outbuffer = bytebuffer.wrap ("OK". GetBytes ());        Channel.write (Outbuffer); }Else{logger.info ("Client closed!!!");        Key.cancel (); }    }} 
Summarize

This article outlines the general process of using NIO for server-side development, but the code obviously still has problems, one is that we only use a thread to perform all operations, including receiving client connections, reading data, and returning data, which is sufficient for this simple demo, but in actual server development, For example, if you want to use NIO to develop your own HTTP server, the server needs to do a lot of local operations, including the resolution of user requests, according to the request routing to an action execution business logic, which is likely to some data from the database read, rendering templates and other operations, very time-consuming, which is undoubtedly called the system bottleneck, Furthermore, using a single thread does not take full advantage of the computing power provided by multicore CPUs. As you'll see in the next article, in Netty based on the reactor model, a boss thread is used to receive client requests and use multiple worker threads to execute specific business logic.

Analysis of the principle of NiO and preliminary----on Netty High Performance server development (i)

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.