The Following Article shall focus on giving a brief detail of How Node.js Works Internally.
Official Documentation of Node.js states:
The Keypoints to take from the Description are
1. Event Driven Architecture
2. Non Blocking I/O Model
Node.js is Centered around resolving the Following Problems:
1. Expensive I/O Operations
Lots of Thread Processing time is wasted while waiting for I/O Operations and Other Asynchronous Tasks like Database Access, File Access, Api Access etc. Thread is wasting time waiting for Async Request to Complete and once the Request is Processed, further Processing is Resumed. This waste Lot of resources and Thread Time.
Node ensures that these Async Tasks are Event Based and Asynchronous. Creating Event Based architecture ensures that the Main Thread is not waiting for the Asynchronous Request to complete. While the Asynch request is processed, Main Thread can switch to another task. This ensures that the Main Thread is always busy. An Event is Fired specifying that the Asynchronous Request is complete and further Processing of the Request can be resumed by the Main Thread.
We all frequently visit Restaurants. Lets understand this concept with Scenerio at Restraurant:
1. You place an Order to the Waiter.
2. Once the Order is placed, the Waiter goes to Chef and place the Order for Preparation.
3. Meanwhile, the Waiter goes to other Tables for taking further Orders.
4. Once the Order is Prepared and Ready, Server brings that Order to you.
In the above scenerio, Waiter is available to take more Requests while the Order is getting Prepared. In Contary, Imagine situation where Waiter waits on your Seat while your Order is getting Prepared, He wont be available to take up other Orders and would end up wasting time waiting for Order to get Prepared.
Similarly, I/O Operation require time to process since it involves external Resources, therefore in case the Thread is Waiting for I/O Request to complete, it will end up wasting Time and Resources. Node.js moves to the Event Based Architecture where I/O Requests are Event Based and once the Request is complete, it will notify the Main Thread to take care of the Further Processing.
2. One Request One Thread Architecture is Expensive
Assigning Independent Threads to Each Request is an Expensive Task. In technologies like C# and Java, each request is processed with an independent Thread. The problem with the approach is that Server has Fixed No of Threads in the Thread Pool. Therefore at any moment of time, Maximum Request processed are equal to number of Threads in Thread Pool.
While processing a Request, it may involve Asynchronous I/O Operations, In that case, the Thread remains busy waiting for the Async Request to complete. This wastes lot of Thread Processing Time waiting for I/O Operations.
Thread might be Idle for maximum time, hence wasting the resources.
Considering the Above Example of Restraurant Again:
1. Hotel with the Capacity of 50 Tables decides to hire Waiters to Cater Every Visiter Independently
2. In that case Hotel need to Hire 50 Waiter to serve the Visitor independently.
In this case, each Waiter shall be wasting Majority of Time Waiting for Order to get Prepared.
This would result in wastage of Resources and Time, which Waiter would have utilized to take other Requests
Thus considering an Architecture, where we have Dedicated Thread to Process Request Single Ended, would waste lots of Resource and Time while waiting for Async Operations. Node.js uses architecture where the I/O Request are handled by the Threads is the Background and a Single Event Loop Thread continuesly runs to take up new request. These request may also be Callback Functions from I/O Operations.
Detailed Node Architecture
Node.js is Single Threaded Event Loop Based Architecture
It is often Mistaken that Node is Multi-Threaded. It is based on Single Threaded Event Loop Architecture.
This Event Loop is Single Threaded. All the Requests are recieved on this Event Thread. Every Requests consists of Asynchronous and Synchronous Execution. The Main Thread is responsible to Execute Only the Synchronous Part of the Request. As soon as Asynch I/O Operation is encountered, the Main Thread allocates a Background thread to process the I/O Operation.
Although we have Multiple Threads in the Background, Node is still said to be Single Threaded since all the Requests are Recieved on the Single Thread and Node internally manages the Execution of Async Process on the Background Threads. At any moment of Time, Main Thread is Executing a Single Request, although there might be multiple threads in the Background working to process Async Task.
Node has Non Blocking I/O Model
Node's Main Thread does not Wait for Async Process to Complete.
While the Background Thread is Executing the Async Function, the Main Thread does not wait for Async Task to complete. It assigns a Background Thread to execute the Asynchronous Task. While the Async Task is executed in the Background, the Main Thread is free to take other Requests. Once the Execution of Background Thread is complete, it returns to the Main Thread for Further Execution.
So considering the Architecture of Node, the Main Thread is always available to process the Requests Synchronously and it is ensured that the Thread is not waiting for Background Process to Complete. Node's Main Thread is continuesly switching between different Requests to execute its Synchronous Part.
Event Based, Instead of Waiting for I/O Operation
The Background Thread uses Event Based Approach to Notify Main Thread
Each Async Task consists of some Callback Function associated with it, once the Async Task is Complete, Background Thread raises Event to Notify the Main Thread about the completion of the Async Task. Main Thread might be busy processing some Other Request, Meanwhile the Request waits on the Main Thread, and as soon as Main Thread is free, it takes up the Callback Request for the Further Execution.