Node. js asynchronous I/O learning notes, node. js learning notes

Source: Internet
Author: User
Tags high cpu usage

Node. js asynchronous I/O learning notes, node. js learning notes

The term "Asynchronous" is widely used in the Web 2.0 wave, which swept the Web along with Javascript and AJAX. Asynchronous programming is rare in most advanced programming languages. PHP can best reflect this feature: it not only shields Asynchronization, but also does not even provide multi-threading. PHP is executed in synchronous blocking mode. This advantage facilitates programmers to write business logic in sequence, but in complex network applications, blocking leads to its inability to make concurrency better.

On the server side, I/O is very expensive, and distributed I/O is more expensive. Only when the backend can respond to resources quickly can the front-end experience be better. Node. js is the first platform that uses Asynchronization as the main programming method and design concept. Along with asynchronous I/O, there are event-driven and single-thread, which constitute the tone of Node. This article describes how Node implements asynchronous I/O.

1. Basic Concepts

"Asynchronous" and "non-blocking" seem to be the same thing. In terms of actual results, both of them achieve the goal of parallelism. However, there are only two methods for computer kernel I/O: blocking and non-blocking. So asynchronous/Synchronous and blocking/non-blocking are actually two things.

1.1 blocking I/O and non-blocking I/O

One feature of blocking I/O is that the call ends only after all operations are completed at the system kernel level. Taking reading a file on a disk as an example, the call ends after the system kernel completes disk tracing, reads data, and copies data to the memory.

Blocking I/O causes the CPU to wait for I/O, wasting the waiting time, And the CPU processing capability cannot be fully utilized. The non-blocking I/O feature is that it will be returned immediately after the call, and the CPU time slice can be used to process other transactions after the return. Because the complete I/O is not completed, the returned immediately is not the data expected by the business layer, but only the status of the current call. In order to obtain the complete data, the application needs to repeatedly call the I/O operation to confirm whether the operation is complete (that is, round robin ). The following polling technologies are required:

1. read: checks the I/O status through repeated calls. It is the most primitive method with the lowest performance.
2. select: Improve read by judging the event status on the file descriptor. The disadvantage is that the maximum number of file descriptors is limited.
3. poll: To improve the select statement, use the linked list method to avoid the maximum number limit. However, if there are many descriptors, the performance is still very low.
4. epoll: If the I/O event is not checked during polling, it will sleep until the event wakes up. This is the most efficient I/O event notification mechanism in Linux.

Round Robin satisfies the need for non-blocking I/O to ensure full data is obtained, but for applications, it can only be counted as one synchronization, because it still needs to wait for I/O to return completely. During the wait period, the CPU is either used to traverse the state of the file descriptor or to sleep the wait event.

1.2 asynchronous I/O in Ideal and Reality

The perfect asynchronous I/O should be a non-blocking call initiated by the application, and the next task can be processed directly without polling, you only need to transmit the data to the application through the signal or callback after I/O is complete.

In reality, asynchronous I/O has different implementations under different operating systems. For example, * the nix platform uses a custom thread pool, and the Windows platform uses the IOCP model. Node provides libuv as an abstract encapsulation layer to encapsulate platform compatibility judgment, and ensures that the implementation of asynchronous I/O between the upper Node and the lower platform is independent of each other. In addition, we often mention that Node is single-threaded. This only means that Javascript Execution is in a single thread, and other thread pools are used for actually completing I/O tasks within the Node.

2. Node asynchronous I/O

2.1 event Loop

The Node execution model is actually an event loop. When a process starts, Node creates an infinite loop, and each execution of the cycle body becomes a Tick. Each Tick process is to check whether there are events waiting for processing. If yes, the events and their related callback functions are taken out. If there are associated callback functions, execute them and enter the next loop. If no event is processed, exit the process.

2.2 observer

Each event cycle contains several observers who are asked to determine whether an event is to be handled. An event loop is a typical producer/consumer model. In Node, events mainly come from network requests, file I/O, etc. These events have corresponding network I/O observers, file I/O observers, etc, the event loop retrieves and processes the event from the observer.

2.3 request object

There is an intermediate product called a request object during the transition from a Javascript call to an I/O operation executed by the kernel. In the simplest Windows fs. the open () method (open a file based on the specified path and parameters and get a file descriptor) is used as an example. From JS calls to built-in modules, libuv is used for system calls, actually, the uv_fs_open () method is called. During the call process, a FSReqWrap request object is created, and the parameters and Methods passed in from the JS layer are encapsulated in this request object, the callback function we are most concerned about is set on the oncompete_sym attribute of this object. After the object is packaged, push the FSReqWrap object into the thread pool for execution.

Now, the JS call returns immediately, and the JS thread can continue to perform subsequent operations. The current I/O operation is waiting for execution in the thread pool, which completes the first phase of asynchronous calling.

2.4 execute callback

Callback notification is the second phase of asynchronous I/O. After the I/O operation in the thread pool is called, it stores the obtained results, notifies IOCP that the current object operation has been completed, and returns the thread to the thread pool. During each Tick execution, the I/O observer of the event loop will call related methods to check whether there are execution-completed requests in the thread pool. If so, the request object is added to the queue of the I/O observer and processed as an event.

3. Non-I/O asynchronous API

Node also has some asynchronous APIs unrelated to I/O, such as the setTimeout () and setInterval () timer, and the process that executes the task asynchronously immediately. nextTick () and setImmdiate () are described here.

3.1 timer API

The setTimeout () and setInterval () browser APIs are consistent. Their implementation principles are similar to those of asynchronous I/O, but they do not require the I/O thread pool. The timer created by calling the timer API will be inserted into a red/black tree inside the timer observer. the Tick of each event loop will iteratively retrieve the timer object from the red/black tree, check whether the scheduled time is exceeded. If the time is exceeded, an event is formed and the callback function is executed immediately. The main problem with the timer is that its timing time is not particularly accurate (within milliseconds, within the tolerable range ).

3.2 run the task API asynchronously now

Before the emergence of Node, many people may call this method to execute a task asynchronously immediately:
Copy codeThe Code is as follows:
SetTimeout (function (){
// TODO
}, 0 );

Due to the characteristics of the event loop, the timer is not accurate enough, and the timer needs to use a red/black tree. The complexity of various operations is O (log (n )). However, the process. nextTick () method only puts the callback function into the queue and extracts and executes the callback function in the next round of Tick. The complexity is O (1), which is more efficient.

In addition, the setImmediate () method is similar to the preceding method, which delays the execution of the callback function. However, the former has a higher priority than the latter, because the event loop checks the observer sequentially. In addition, the callback function of the former is saved in an array, and all the callback functions in the array are executed in every round of Tick. The latter result is saved in the linked list, only One callback function is executed for each round of Tick.

4. event-driven and high-performance servers

Taking fs. open () as an example, we described how Node can implement asynchronous I/O. In fact, Node also applies asynchronous I/O for network socket processing, which is also the basis for Node to build Web servers. Classic server models include:

1. synchronous mode: only one request can be processed at a time, and all other requests are waiting.
2. Each process/Request: Start a process for each request, but the system resources are limited and not scalable.
3. Each thread/Request: Start a thread for each request. The thread is lighter than the process, but each thread occupies a certain amount of memory. When a large number of concurrent requests arrive, the memory will soon be used up.

The famous Apache adopts the form of each thread/request, which is also the reason why it is difficult to cope with high concurrency. Node processes requests in an event-driven manner, saving the overhead of creating and destroying threads. At the same time, the context switching cost is also low because the operating system schedules tasks because of a small number of threads. Node can process requests in an orderly manner even when a large number of connections exist.

Nginx, a well-known server, also abandons the multi-thread approach and adopts the same event-driven approach as Node. Today, Nginx is a great replacement for Apache. Nginx is written in pure C mode with high performance. However, Nginx is only suitable for Web servers and is used for reverse proxy or Server Load balancer. Node can build the same functions as Nginx, and can handle various specific services, with good performance. In actual projects, we can combine them to achieve the best performance of the application.


Nodejs has an asynchronous example of Fibonacci. I doubt the role of processnextTick ().

You can run two fibonacciAsync () to see that it is asynchronous.

How can programmers persuade the boss to adopt Nodejs?

Introduction: Recently, Node. js is very popular in the industry, and there are countless news about it. There are indications that more companies in the industry are paying attention to and considering using Node. js. As the saying goes, how can programmers successfully persuade the boss to listen to your suggestions? To address this topic, the author Felix published a blog post, which shares some constructive guidelines. The csdn r & D channel now compiles this article and shares it with developers. You are also welcome to publish your own Node. js practices. Poor use cases Apps's high CPU usage has always been in favor of Node. js, but here are a few use cases, but the results are not satisfactory. The most obvious difference is that the CPU usage and I/O operations of Apps are extremely high. Therefore, if you want to write a video encoding software, such as artificial intelligence or software with high CPU usage, do not use Node. js. Using C or C ++ will be better. Even so, Node. js allows you to easily write C ++ plug-ins. Therefore, you can use it as a script engine for super algorithms. Simple CRUD/HTML javasnode. js will eventually become a good tool for compiling Web applications. However, you cannot expect it to provide more benefits for you like PHP, Ruby, and Python. Maybe your application will achieve more scalability, but it will not bring you more traffic because it is written in Node. js. You may be excited when we see some nice frameworks of Node. js. In fact, there are no more powerful application functions than Rails, CakePHP or Django frameworks. If your application only renders HTML based on some databases, using Node. js will not bring you any benefits. NoSQL + Node. js + various trendy words if the system architecture of your next application reads like a recipe for NoSQL ingredients, take some time to read the following content. Redis, CouchDB, MongoDB, Riak, Casandra, and so on seem attractive and hard to resist. If you are using Node. js, you should not attach some technologies you do not know at all. Of course, there is also a case study of rational use of the document database. However, if you want to develop a commercial project, stick to conservative database technologies (such as S or MySQL) to meet your needs. The outstanding use case of JSON APIs to create a lightweight REST/json api is indeed a highlight of Node. js. If you want to encapsulate other data sources (such as databases) or Web servers to expose them through the JSON interface, combining non-blocking I/O modules with JavaScript is a good choice. If you plan to write an AJAX single page application (such as Gmail), Node. js is very suitable. Obtain more requests in a very short response time, share data between the client and the server, and perform a lot of processing for modern Web applications on the client, Node. js can meet your needs. Unix tool Shelling out to unix tools currently Node. js is still very young, and it is trying to re-invent various types of software for itself. But the better way is to go deep into the vast world of command line tools. Node can output these thousands of sub-processes in stream mode, which also makes it an ideal choice for enterprises. The traditional Web stack of Streaming data processes http requests and responses as meta events. However, they are mobile, and many great Node. js applications are created using this advantage. Here is a great case. When you perform real-time parsing and uploading files, you can also create a proxy between different data layers. With Node. js, you can easily develop real-time software systems. Such as Twitter, chat tools, sports lottery, or instant messaging network interfaces. However, it is worth noting that JavaScript is dynamic.

Related Article

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.