Node.jsのアーキテクチャーは、シングルスレッドのイベントループです。
今日は、Node JSのアーキテクチャとシングルスレッドのイベントループモデルについて見ていきます。以前の投稿で、Node JSの基本、Node JSのコンポーネント、Node JSのインストールについて議論しました。
Node.jsのアーキテクチャ。
Node JSプログラミングの例を始める前に、Node JSアーキテクチャについての基本的な知識を持つことが重要です。この投稿では、「Node JSの内部動作、どのような処理モデルを採用しているか、Node JSがシングルスレッドモデルで並行リクエストをどのように処理するか」などについて話し合います。
Node.jsのシングルスレッドイベントループモデル
私たちがすでに話し合ったように、Node JSアプリケーションは「シングルスレッドのイベントループモデル」アーキテクチャを使用して、複数の同時クライアントを処理します。JSP、Spring MVC、ASP.NET、HTML、Ajax、jQueryなど、多くのウェブアプリケーション技術があります。ただし、これらの技術はすべて、「マルチスレッドのリクエスト-レスポンス」アーキテクチャを使用して複数の同時クライアントを処理します。私たちは既に「マルチスレッドのリクエスト-レスポンス」アーキテクチャについて詳しく知っています。なぜなら、ほとんどのウェブアプリケーションフレームワークで使用されているからです。しかし、Node JSプラットフォームはなぜ異なるアーキテクチャを選択したのでしょうか。マルチスレッドとシングルスレッドのイベントループアーキテクチャの主な違いは何でしょうか。どのウェブ開発者もNode JSを学び、簡単にアプリケーションを開発することができます。ただし、Node JSの内部構造を理解しないと、Node JSアプリケーションの設計と開発がうまく行えません。したがって、Node JSアプリケーションの開発を開始する前に、まずNode JSプラットフォームの内部構造を学びましょう。
Node JSプラットフォーム
Node.jsプラットフォームは、複数の同時クライアントを処理するために「シングルスレッドのイベントループ」アーキテクチャを使用しています。それでは、複数のスレッドを使用せずにクライアントのリクエストを並行して処理する方法は実際にはどのようなものでしょうか。イベントループモデルとは何ですか?これらの概念について順番に説明していきます。まず、「シングルスレッドのイベントループ」アーキテクチャについて説明する前に、有名な「マルチスレッドのリクエスト-レスポンス」アーキテクチャについて説明します。
伝統的なウェブアプリケーションの処理モデル
一般に、Node.jsを使用せずに開発された任意のウェブアプリケーションは、「マルチスレッド型のリクエスト-レスポンス」モデルに従います。単純に言えば、このモデルはリクエスト/レスポンスモデルと呼ぶことができます。クライアントはリクエストをサーバーに送信し、サーバーはクライアントのリクエストに基づいて処理を行い、レスポンスを準備してクライアントに送信します。このモデルではHTTPプロトコルが使用されます。HTTPは状態を持たないプロトコルであるため、このリクエスト/レスポンスモデルも状態を持たないモデルと呼ぶことができます。したがって、これをリクエスト/レスポンス状態なしモデルと呼ぶことができます。ただし、このモデルでは複数のスレッドを使用して同時のクライアントリクエストを処理します。このモデルの内部について説明する前に、以下の図を確認してください。リクエスト/レスポンスモデルの処理手順:
- Clients Send request to Web Server.
- Web Server internally maintains a Limited Thread pool to provide services to the Client Requests.
- Web Server is in infinite Loop and waiting for Client Incoming Requests
- Web Server receives those requests.Web Server pickup one Client Request
Pickup one Thread from Thread pool
Assign this Thread to Client Request
This Thread will take care of reading Client request, processing Client request, performing any Blocking IO Operations (if required) and preparing Response
This Thread sends prepared response back to the Web Server
Web Server in-turn sends this response to the respective Client.
サーバーは無限ループで待機し、上記で述べたすべてのサブステップをnクライアントすべてに対して実行します。つまり、このモデルではクライアントリクエストごとに1つのスレッドが作成されます。複数のクライアントリクエストがブロッキングIO操作を必要とする場合、ほとんどのスレッドが自分のレスポンスの準備に忙しくなります。その結果、残りのクライアントリクエストはより長い時間を待たなければなりません。図の説明:
- Here “n” number of Clients Send request to Web Server. Let us assume they are accessing our Web Application concurrently.
- Let us assume, our Clients are Client-1, Client-2… and Client-n.
- Web Server internally maintains a Limited Thread pool. Let us assume “m” number of Threads in Thread pool.
- Web Server receives those requests one by one.Web Server pickup Client-1 Request-1, Pickup one Thread T-1 from Thread pool and assign this request to Thread T-1
Thread T-1 reads Client-1 Request-1 and process it
Client-1 Request-1 does not require any Blocking IO Operations
Thread T-1 does necessary steps and prepares Response-1 and send it back to the Server
Web Server in-turn send this Response-1 to the Client-1Web Server pickup another Client-2 Request-2, Pickup one Thread T-2 from Thread pool and assign this request to Thread T-2
Thread T-2 reads Client-1 Request-2 and process it
Client-1 Request-2 does not require any Blocking IO Operations
Thread T-2 does necessary steps and prepares Response-2 and send it back to the Server
Web Server in-turn send this Response-2 to the Client-2Web Server pickup another Client-n Request-n, Pickup one Thread T-n from Thread pool and assign this request to Thread T-n
Thread T-n reads Client-n Request-n and process it
Client-n Request-n require heavy Blocking IO and computation Operations
Thread T-n takes more time to interact with external systems, does necessary steps and prepares Response-n and send it back to the Server
Web Server in-turn send this Response-n to the Client-nIf “n” is greater than “m” (Most of the times, its true), then server assigns Threads to Client Requests up to available Threads. After all m Threads are utilized, then remaining Client’s Request should wait in the Queue until some of the busy Threads finish their Request-Processing Job and free to pick up next Request. If those threads are busy with Blocking IO Tasks (For example, interacting with Database, file system, JMS Queue, external services etc.) for longer time, then remaining clients should wait longer time. - Once Threads are free in Thread Pool and available for next tasks, Server pickup those threads and assign them to remaining Client Requests.
- Each Thread utilizes many resources like memory etc. So before going those Threads from busy state to waiting state, they should release all acquired resources.
要求/応答ステートレスモデルのデメリット:
- Handling more and more concurrent client’s request is bit tough.
- When Concurrent client requests increases, then it should use more and more threads, finally they eat up more memory.
- Sometimes, Client’s Request should wait for available threads to process their requests.
- Wastes time in processing Blocking IO Tasks.
Node JSのアーキテクチャーは、シングルスレッドのイベントループです。
Node.jsのプラットフォームは、リクエスト/レスポンスのマルチスレッドでステートレスなモデルに従いません。代わりに、シングルスレッドでイベントループモデルに従います。Node.jsの処理モデルは、主にJavaScriptのイベントベースモデルとJavaScriptのコールバックメカニズムを基にしています。JavaScriptのイベントとコールバックメカニズムがどのように動作するかについての十分な知識を持っている必要があります。知らない場合は、まずこれらの投稿やチュートリアルを読んで、次のステップに進む前にアイデアを得てください。Node.jsはこのアーキテクチャに従うため、非常に簡単により多くの同時クライアントリクエストを処理することができます。このモデルの内部について説明する前に、まず下の図を見てください。この図では、Node.jsの内部の各ポイントを説明するために設計しました。Node.jsの処理モデルの中心は「イベントループ」です。これを理解すれば、Node.jsの内部を理解するのは非常に簡単です。シングルスレッドのイベントループモデルの処理手順:
- Clients Send request to Web Server.
- Node JS Web Server internally maintains a Limited Thread pool to provide services to the Client Requests.
- Node JS Web Server receives those requests and places them into a Queue. It is known as “Event Queue”.
- Node JS Web Server internally has a Component, known as “Event Loop”. Why it got this name is that it uses indefinite loop to receive requests and process them. (See some Java Pseudo code to understand this below).
- Event Loop uses Single Thread only. It is main heart of Node JS Platform Processing Model.
- Even Loop checks any Client Request is placed in Event Queue. If no, then wait for incoming requests for indefinitely.
- If yes, then pick up one Client Request from Event QueueStarts process that Client Request
If that Client Request Does Not requires any Blocking IO Operations, then process everything, prepare response and send it back to client.
If that Client Request requires some Blocking IO Operations like interacting with Database, File System, External Services then it will follow different approachChecks Threads availability from Internal Thread Pool
Picks up one Thread and assign this Client Request to that thread.
That Thread is responsible for taking that request, process it, perform Blocking IO operations, prepare response and send it back to the Event Loop
Event Loop in turn, sends that Response to the respective Client.
ダイアグラムの説明:
- Here “n” number of Clients Send request to Web Server. Let us assume they are accessing our Web Application concurrently.
- Let us assume, our Clients are Client-1, Client-2… and Client-n.
- Web Server internally maintains a Limited Thread pool. Let us assume “m” number of Threads in Thread pool.
- Node JS Web Server receives Client-1, Client-2… and Client-n Requests and places them in the Event Queue.
- Node JS Even Loop Picks up those requests one by one.Even Loop pickups Client-1 Request-1
Checks whether Client-1 Request-1 does require any Blocking IO Operations or takes more time for complex computation tasks.
As this request is simple computation and Non-Blocking IO task, it does not require separate Thread to process it.
Event Loop process all steps provided in that Client-1 Request-1 Operation (Here Operations means Java Script’s functions) and prepares Response-1
Event Loop sends Response-1 to Client-1Even Loop pickups Client-2 Request-2
Checks whether Client-2 Request-2does require any Blocking IO Operations or takes more time for complex computation tasks.
As this request is simple computation and Non-Blocking IO task, it does not require separate Thread to process it.
Event Loop process all steps provided in that Client-2 Request-2 Operation and prepares Response-2
Event Loop sends Response-2 to Client-2Even Loop pickups Client-n Request-n
Checks whether Client-n Request-n does require any Blocking IO Operations or takes more time for complex computation tasks.
As this request is very complex computation or Blocking IO task, Even Loop does not process this request.
Event Loop picks up Thread T-1 from Internal Thread pool and assigns this Client-n Request-n to Thread T-1
Thread T-1 reads and process Request-n, perform necessary Blocking IO or Computation task, and finally prepares Response-n
Thread T-1 sends this Response-n to Event Loop
Event Loop in turn, sends this Response-n to Client-n
クライアントリクエストは、1つまたは複数のJavaScript関数の呼び出しです。JavaScript関数は他の関数を呼び出すこともあり、また、コールバック関数の特性を利用することもあります。したがって、各クライアントリクエストは以下のような形になります。例えば:
function1(function2,callback1);
function2(function3,callback2);
function3(input-params);
日本の友達にメールを送る。
- If you don’t understand how these functions are executed, then I feel you are not familiar with Java Script Functions and Callback mechanism.
- We should have some idea about Java Script functions and Callback mechanisms. Please go through some online tutorial before starting our Node JS Application development.
Node.js アーキテクチャ – シングルスレッドイベントループの利点
-
- より多くの同時クライアントの要求を処理することは非常に簡単です。
-
- 私たちのNode JSアプリケーションは、ますます多くの同時クライアントの要求を受け取っても、イベントループのおかげでさらに多くのスレッドを作成する必要はありません。
- Node JSアプリケーションはスレッドを少なく使用するため、リソースやメモリも少なく利用することができます。
イベントループの疑似コード
「私はJavaの開発者ですので、「イベントループの動作方法」をJavaの専門用語で説明しようと思います。これは純粋なJavaのコードではありませんが、皆さんなら理解できると思います。もし理解に問題がある場合は、コメントを残してください。」
public class EventLoop {
while(true){
if(Event Queue receives a JavaScript Function Call){
ClientRequest request = EventQueue.getClientRequest();
If(request requires BlokingIO or takes more computation time)
Assign request to Thread T1
Else
Process and Prepare response
}
}
}
それがNode JSアーキテクチャとNode JSのシングルスレッドイベントループのすべてです。