Nodejs principle of Operation-libuv Chapter

Source: Internet
Author: User
Tags builtin

Objective

This should be nodejs of the principle of the 7th share, this post, a short period of time will not share the principle of Nodejs, will stop for a period of time, PS: not not more, but will dig new pits, recently in the research RPG Maker MV, Blockchain, cloud computing, may update some related articles, or related teaching.

Back to the point, the difficulty with asynchronous programming is that requests and responses do not occur sequentially. In the case of HTTP server, asynchronous programming gives the server high concurrency quality, and he can continuously accept and process requests at a very small resource cost. But fast processing requests do not represent fast return requests, and high concurrency is not the same as fast feedback.

In Nodejs, LIBUV provides the possibility for the implementation of asynchronous programming. LIBUV provides APIs for Builtin modules , which are used to support the asynchronous processing of requests and data returns.

This share, we mainly discuss the operating principle of libuv, from two angles:

1) Architecture of LIBUV

2) case, from the point of view of detail how LIBUV treats different I/O requests, in different ways to complete the asynchronous request and return the data.

Architecture of the LIBUV

From left to right can be divided into two parts, Network I/O related requests, the other part of file I/o,dns Ops and user code composition.

The process of LIBUV details is shown, and the code in the diagram is simple, including 2 parts:

1. Server.listen () is the code that is typically put in the last step when creating a TCP server. primary specifies the port on which the server works and the callback function.

2. Fs.open () is an asynchronous way to open a file.

Selecting the two example is simple because the LIBUV frame composition is visible: The LIBUV uses different mechanisms for Network I/O and File I/O .

The right half is divided into two main parts:

1. Main thread: The main thread is also a ready-made node to execute when it is started. When node starts, it completes a series of initialization actions, launches the V8 engine, and enters the next loop.

2. Thread pool: The number of thread pools can be configured by the environment variable uv_threadpool_size, with a maximum of 128, and 4 by default.

Network I/O

V8 engine executes the process of calling Builtin module Tcp_wrap starting from Server.listen ().

During the creation of the TCP link, LIBUV directly participates in the Tcpwrap::listen () call in the tcp_wrap.cc function Uv_listen () starts to the end of execution Uv_io_start (). The seemingly ephemeral process is actually an interrupt handling mechanism similar to the Linux kernel.

The Uv_io_start () load inserts the handle into the processed water queue. The benefit is that requests can be processed immediately. The lower part of the interrupt processing mechanism is similar to the data processing operation and is left to the main thread to complete the processing.

The code logic is simple to see if the loop contains handle, if you have traversed the default loop.

File I/O

Here we look at File I/O.

Like network I/O, our application relies on the FS module, followed by a builtin module node_file.cc as support. Node_file.cc contains a variety of interfaces for our commonly used file operations, such as open, read, write, Chmod,chown, and so on. But at the same time, they all support asynchronous mode. We study the specific implementation details through the open () function in node_file.cc.

If you use code reading tools like source insight to track the order of code calls, it's easy to see that for asynchronous mode, the Open () function enters the function uv_fs_open () after a series of auxiliary operations, and passes in a Fsreqwrap object.

Fsreqwrap (), which can be seen from the name, is a wrap, and is a request related to FS. That is, it is based on an out-of-the-box mechanism to implement request operations related to FS. This ready-made mechanism is reqwrap. Well, it's also a wrap. When you're not crazy, look at 16. This is a complete demonstration of the Fsreqwrap class inheritance relationship.

In addition to Fsreqwrap, there are other wrap, such as pipeconnectwrap,tcpconnectwrap and so on. Each wrap is a request type service. But these wrap are the actions of node itself, and what is related to LIBUV? The FSREQWRAP key data structure uv_fs_s req__ is shown.

Let's look back at the Uv_fs_open (). When this function is called, req__ is passed in as an important parameter. Inside Uv_fs_open (), req__ is added to the end of the work queue. Figure 3 thread in the thread pool will go to collect these request for processing. Each request is much like a pasteboard that binds the event loop, the work queue, the handler function (working ()), and the request end handler (done ()). The binding operation is done in Uv__work_submit (). For example, here req__, work () bound on it is uv__fs_work (), Done () is Uv__fs_done ().

Here's a more interesting question that deserves a little extra look. When was our thread pool built?

The answer is: when Uv__work_submit () is called asynchronously for the first time.

The entry function for each thead is the worker () in the THREADPOOL.C. The working logic is simple, and then the request in the work queue is taken out, and the job () function bound on the request is executed. Where does the done () function on the request that we mentioned earlier be executed? This is also a more interesting operation. LIBUV notifies the event loop via Uv_async_send () to execute the corresponding callback function, which is the done () function that we bind to the request. Uv__work_done () is used to complete such operations.

Uv_async_send () communicates with the main thread through the pipe.

In this section, I take a fsreqwrap and the open () function as an example, describing the various operations involved in LIBUV processing this file I/O request:

    1. Build thread pool (only once)
    2. Bind the event loop associated with each request req__, Work queue, work (), done ()
    3. The thread worker () is used to process every request in the work queue and executes the working ()
    4. Uv_async_send () notifies event loop to perform done ()

Nodejs principle of Operation-libuv Chapter

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.