Node.js Architecture (Part 3)

Node.js Architecture (Part 3)

Daily short news for you
  • How I wish I had discovered this repository earlier. github/opensource.guide is a place that guides everyone on everything about Open Source. From how to contribute code, how to start your own open-source project, to the knowledge that anyone should know when stepping into this field 🤓

    Especially, this content is directly from Github.

    » Read more
  • Just the other day, I mentioned dokploy.com and today I came across coolify.io - another open-source project that can replace Heroku/Netlify/Vercel.

    From what I've read, Coolify operates based on Docker deployment, which allows it to run most applications.

    Coolify offers an interface and features that make application deployment simpler and easier.

    Could this be the trend for application deployment in the future? 🤔

    » Read more
  • One of the things I really like about command lines is their 'pipeline' nature. You can imagine each command as a pipe; when connected together, they create a flow of data. The output of one pipe becomes the input of another... and so on.

    In terms of application, there are many examples; you can refer to the article Practical Data Processing Using Commands on MTTQVN Statement File. By combining commands, we turn them into powerful data analysis tools.

    Recently, I combined the wrangler command with jq to make it easier to view logs from the worker. wrangler is Cloudflare's command line interface (CLI) that integrates many features. One of them helps us view logs from Worker using the command:

    $ wrangler tail --config /path/to/wrangler.toml --format json

    However, the logs from the above command contain a lot of extraneous information, spilling over the screen, while we only want to see a few important fields. So, what should we do?

    Let’s combine it with jq. jq is a very powerful JSON processing command. It makes working with JSON data in the terminal much easier. Therefore, to filter information from the logs, it’s quite simple:

    $ wrangler tail --config /path/to/wrangler.toml --format json | jq '{method: .event.request.method, url: .event.request.url, logs }'

    The above command returns structured JSON logs consisting of only 3 fields: method, url, and logs 🔥

    » Read more

Node.js utilizes the Event Loop to handle asynchronous I/O tasks. Do you truly understand how the Event Loop operates?

Phases of the Event Loop

Previously, it was mentioned that the Event Loop monitors whether the Call Stack is empty and if the Event Queue contains any functions waiting to be executed, it puts them back into the Call Stack. This process is carried out through phases, as depicted in the following diagram:

Các pha (Phases) của Event Loop

  • Timers: executes scheduled callback functions with setTimeout and setInterval.
  • I/O callbacks: performs most callback operations except close callbacks, timers callbacks, and setImmediate().
  • Idle, prepare: used for internal node.js processing.
  • Poll: retrieves new I/O events, accepts incoming connections, and processes data.
  • Check: handles setImmediate callback functions.
  • Close callbacks: executes callback functions for "close" events. For example, socket.on("close").

This proves that the phases of the Event Loop are executed by the main thread. Each phase represents how the Event Loop determines which pending callback functions to put into the Call Stack for execution.

The phases of the Event Loop also explain the execution order of certain functions in node.js, such as setTimeout(cb, 0), setImmediate(), and process.nextTick(cb), which we will delve deeper into in a future article.

Recap

In summary, node.js has two crucial building components:

Libuv - Cross-platform Asynchronous I/O

libuv is a cross-platform library that focuses on asynchronous I/O. It is primarily developed for use by node.js.

Libuv includes an Event Loop, asynchronous TCP/UDP, asynchronous file handling, thread pooling, child processes, and their independent handling.

V8 JavaScript Engine

V8 is an open-source project from Google, written in C++. It is used in Chrome and Node.js.

It implements ECMAScript and WebAssembly, while running on Windows 7 and above, macOS 10.12+, and Linux.

V8 contains heap memory allocation capabilities, Call Stack execution, garbage collector, optimizing compiler, and JavaScript interpreter.

Node.js utilizes the V8 JavaScript Engine and is therefore called a V8 embedder. As per the requirements of the V8 Engine, the embedder must implement an event loop. Node.js has chosen libuv to implement the loop. This is where V8 and libuv are connected through C++ bindings.

As a single-threaded environment, node.js has only one event loop. Between each run of the event loop, node.js checks for any pending asynchronous I/O tasks and exits if there are no events. Essentially, the event loop does not create an instantaneous response until there is a waiting callback to be processed. Ultimately, a node.js application ends when there are no events in either the Call Stack or Event Queue.

Single-Threaded Concurrent Model

To summarize the concurrency model in a single thread, the Event Loop and Call Stack are used to build the asynchronous I/O model as follows:

  • The node.js application is executed by node.js.
  • CPU-bound functions (high CPU usage) are synchronously executed on the main thread.
  • If the function is an asynchronous I/O, it is pushed to the thread pool for asynchronous execution while the main thread continues execution.
  • After the asynchronous function completes, the thread pool pushes the callback function and event into the Event Queue.
  • The event loop utilizes the main thread to monitor any callback functions waiting to be processed in the Event Queue if the Call Stack is empty. It puts the callback functions back into the Call Stack for execution if the Call Stack is empty.

When to Use Node.js?

Node.js simply provides an asynchronous I/O model, unblocked even with a single thread. This makes it more suitable for deep I/O applications. CPU-intensive applications will not be suitable for node.js as it would block the execution on that single thread.

Due to the usage of the JavaScript programming language in node.js, developers can create full Application Stacks solely using JavaScript.

Premium
Hello

The secret stack of Blog

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

As a developer, are you curious about the technology secrets or the technical debts of this blog? All secrets will be revealed in the article below. What are you waiting for, click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (0)

Leave a comment...
Scroll or click to go to the next page