目次
高同時実行戦略
イベント ループ
動作原理
CPU密集型是短板
适用场景
ホームページ ウェブフロントエンド jsチュートリアル Nodejs のイベント ループ メカニズムの詳細については、こちらをご覧ください。

Nodejs のイベント ループ メカニズムの詳細については、こちらをご覧ください。

Jan 05, 2021 pm 05:40 PM
nodejs

この記事では、nodejs イベント ループ メカニズムを理解します。一定の参考値があるので、困っている友達が参考になれば幸いです。

Nodejs のイベント ループ メカニズムの詳細については、こちらをご覧ください。

関連する推奨事項: 「nodejs チュートリアル

Node.js はイベント駆動型の非同期 I/O を使用して、単一の-スレッド化された、同時実行性の高い JavaScript ランタイム環境、およびシングル スレッドとは、同時に実行できる処理が 1 つだけであることを意味します。では、Node.js はどのようにしてシングル スレッドを通じて高い同時実行性と非同期 I/O を実現するのでしょうか?この記事では、この問題に焦点を当てて、Node.js のシングルスレッド モデルについて説明します。

高同時実行戦略

一般に、高同時実行の解決策は、マルチスレッド モデルを提供することです。サーバーは、クライアントのリクエストごとにスレッドを割り当て、同期を使用します。 I/O の場合、システムはスレッド スイッチングを使用して、同期 I/O 呼び出しの時間オーバーヘッドを補います。たとえば、Apache にはこの戦略があり、一般に I/O には時間がかかるため、高いパフォーマンスを実現するのは困難ですが、非常にシンプルで複雑な対話ロジックを実装できます。

実際、ほとんどの Web サイトのサーバー側では、あまり多くの計算は行わず、リクエストを受信した後、そのリクエストを他のサービスに渡して処理 (データベースの読み取りなど) を行い、結果を返し、最後に結果をクライアントに送信します。そこで、Node.js では、アクセス要求ごとにスレッドを割り当てるのではなく、メインスレッドですべての要求を処理し、I/O 操作を非同期で処理するシングルスレッド モデルを採用しています。により、スレッドの作成、破棄、切り替えに必要なオーバーヘッドと複雑さが回避されます。

イベント ループ

Node.js は、メイン スレッドで イベント キューを維持します。リクエストが受信されると、リクエストは An として扱われます。イベントはこのキューに配置され、引き続き他のリクエストを受信します。メインスレッドがアイドル状態 (アクセス要求がないとき) に、イベント キューの循環を開始し、キュー内に処理すべきイベントがあるかどうかを確認します。タスクを個別に処理してコールバックします。関数は上位層の呼び出しに戻ります。I/O タスクの場合は、スレッド プール からスレッドを取り出してイベントを処理し、コールバックを指定します関数を実行し、キュー内の他のイベントを循環し続けます。

スレッド内の I/O タスクが完了すると、指定されたコールバック関数が実行され、完了したイベントがイベント キューの最後に配置され、イベント ループを待ちます。再度イベントに送信すると、直接処理されて上位層の呼び出しに返されます。この処理を イベント ループ (イベント ループ)と呼び、その動作原理を次の図に示します。

この図は、イベント ループの動作原理です。 Node.js 全体は、左から右、上から下の順に、アプリケーション レイヤーV8 エンジン レイヤーNode API の 4 つのレイヤーに分割されます。レイヤーLIBUVレイヤー。

アプリケーション層: つまり、JavaScript インタラクション層です。最も一般的なものは、http、fs

V8 エンジン層などの Node.js モジュールです。 、V8 エンジンを使用して JavaScript 構文を解析し、下位 API

NodeAPI レイヤーと対話します。通常は C 言語で実装される上位モジュールに、オペレーティング システムと対話するためのシステム コールを提供します。

LIBUV レイヤー: イベント ループ、ファイル操作などを実装するクロスプラットフォームの最下位カプセル化であり、Node.js の非同期実装の中核です。

Linux プラットフォームであっても Windows プラットフォームであっても、Node.js は スレッド プール を通じて内部的に非同期 I/O 操作を完了し、LIBUV はプラットフォームごとに異なるユニファイド コールで実装されます。 。したがって、Node.js のシングル スレッドは、JavaScript がシングル スレッドで実行されることを意味するだけであり、Node.js がシングル スレッドであることを意味するわけではありません。

動作原理

Node.js の非同期実装の核心はイベントです。つまり、各タスクを イベント として扱います。イベント ループを介して処理することで、非同期効果がシミュレートされます この事実をより具体的かつ明確に理解して受け入れるために、疑似コードを使用してその動作原理を説明しましょう。

[1] イベント キューの定義

キューなので先入れ先出し (FIFO) データ構造であり、JS を使用します。これを説明するには、次のように配列を使用します。

/**
 * 定义事件队列
 * 入队:push()
 * 出队:shift()
 * 空队列:length == 0
 */
globalEventQueue: []
ログイン後にコピー

配列を使用してキュー構造をシミュレートします。配列の最初の要素はキューの先頭であり、配列の最後の要素はキューの末尾です。 Push()はキューの最後尾に要素を挿入すること、shift()はキューの先頭から要素をポップすることです。これは単純なイベント キューを実装します。

【2】定義受信リクエストエントリ

各リクエストは、以下に示すようにインターセプトされ、処理関数に入力されます。

/**
 * 接收用户请求
 * 每一个请求都会进入到该函数
 * 传递参数request和response
 */
processHttpRequest:function(request,response){
    
    // 定义一个事件对象
    var event = createEvent({
        params:request.params, // 传递请求参数
        result:null, // 存放请求结果
        callback:function(){} // 指定回调函数
    });

    // 在队列的尾部添加该事件   
    globalEventQueue.push(event);
}
ログイン後にコピー

这个函数很简单,就是把用户的请求包装成事件,放到队列里,然后继续接收其他请求。

【3】定义 Event Loop

当主线程处于空闲时就开始循环事件队列,所以我们还要定义一个函数来循环事件队列:

/**
 * 事件循环主体,主线程择机执行
 * 循环遍历事件队列
 * 处理非IO任务
 * 处理IO任务
 * 执行回调,返回给上层
 */
eventLoop:function(){
    // 如果队列不为空,就继续循环
    while(this.globalEventQueue.length > 0){
        
        // 从队列的头部拿出一个事件
        var event = this.globalEventQueue.shift();
        
        // 如果是耗时任务
        if(isIOTask(event)){
            // 从线程池里拿出一个线程
            var thread = getThreadFromThreadPool();
            // 交给线程处理
            thread.handleIOTask(event)
        }else {
            // 非耗时任务处理后,直接返回结果
            var result = handleEvent(event);
            // 最终通过回调函数返回给V8,再由V8返回给应用程序
            event.callback.call(null,result);
        }
    }
}
ログイン後にコピー

主线程不停的检测事件队列,对于 I/O 任务,就交给线程池来处理,非 I/O 任务就自己处理并返回。

【4】处理 I/O 任务

线程池接到任务以后,直接处理IO操作,比如读取数据库:

/**
 * 处理IO任务
 * 完成后将事件添加到队列尾部
 * 释放线程
 */
handleIOTask:function(event){
    //当前线程
    var curThread = this; 

    // 操作数据库
    var optDatabase = function(params,callback){
        var result = readDataFromDb(params);
        callback.call(null,result)
    };
    
    // 执行IO任务
    optDatabase(event.params,function(result){
        // 返回结果存入事件对象中
        event.result = result; 

        // IO完成后,将不再是耗时任务
        event.isIOTask = false; 
        
        // 将该事件重新添加到队列的尾部
        this.globalEventQueue.push(event);
        
        // 释放当前线程
        releaseThread(curThread)
    })
}
ログイン後にコピー

当 I/O 任务完成以后就执行回调,把请求结果存入事件中,并将该事件重新放入队列中,等待循环,最后释放当前线程,当主线程再次循环到该事件时,就直接处理了。

总结以上过程我们发现,Node.js 只用了一个主线程来接收请求,但它接收请求以后并没有直接做处理,而是放到了事件队列中,然后又去接收其他请求了,空闲的时候,再通过 Event Loop 来处理这些事件,从而实现了异步效果,当然对于IO类任务还需要依赖于系统层面的线程池来处理。

因此,我们可以简单的理解为:Node.js 本身是一个多线程平台,而它对 JavaScript 层面的任务处理是单线程的。

CPU密集型是短板

至此,对于 Node.js 的单线程模型,我们应该有了一个简单而又清晰的认识,它通过事件驱动模型实现了高并发和异步 I/O,然而也有 Node.js 不擅长做的事情:

上面提到,如果是 I/O 任务,Node.js 就把任务交给线程池来异步处理,高效简单,因此 Node.js 适合处理I/O密集型任务。但不是所有的任务都是 I/O 密集型任务,当碰到CPU密集型任务时,即只用CPU计算的操作,比如要对数据加解密(node.bcrypt.js),数据压缩和解压(node-tar),这时 Node.js 就会亲自处理,一个一个的计算,前面的任务没有执行完,后面的任务就只能干等着 。如下图所示:

在事件队列中,如果前面的 CPU 计算任务没有完成,后面的任务就会被阻塞,出现响应缓慢的情况,如果操作系统本身就是单核,那也就算了,但现在大部分服务器都是多 CPU 或多核的,而 Node.js 只有一个 EventLoop,也就是只占用一个 CPU 内核,当 Node.js 被CPU 密集型任务占用,导致其他任务被阻塞时,却还有 CPU 内核处于闲置状态,造成资源浪费。

因此,Node.js 并不适合 CPU 密集型任务。

适用场景

RESTful API - 请求和响应只需少量文本,并且不需要大量逻辑处理, 因此可以并发处理数万条连接。

聊天服务 - 轻量级、高流量,没有复杂的计算逻辑。

更多编程相关知识,请访问:编程教学!!

以上がNodejs のイベント ループ メカニズムの詳細については、こちらをご覧ください。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Nodejsとvuejsの違い Nodejsとvuejsの違い Apr 21, 2024 am 04:17 AM

Node.js はサーバー側の JavaScript ランタイムであり、Vue.js は対話型ユーザー インターフェイスを作成するためのクライアント側の JavaScript フレームワークです。 Node.js はバックエンド サービス API 開発やデータ処理などのサーバー側開発に使用され、Vue.js はシングルページ アプリケーションや応答性の高いユーザー インターフェイスなどのクライアント側開発に使用されます。

Nodejs はバックエンド フレームワークですか? Nodejs はバックエンド フレームワークですか? Apr 21, 2024 am 05:09 AM

Node.js は、高いパフォーマンス、スケーラビリティ、クロスプラットフォーム サポート、豊富なエコシステム、開発の容易さなどの機能を備えているため、バックエンド フレームワークとして使用できます。

Nodejsをmysqlデータベースに接続する方法 Nodejsをmysqlデータベースに接続する方法 Apr 21, 2024 am 06:13 AM

MySQL データベースに接続するには、次の手順に従う必要があります。 mysql2 ドライバーをインストールします。 mysql2.createConnection() を使用して、ホスト アドレス、ポート、ユーザー名、パスワード、データベース名を含む接続オブジェクトを作成します。 connection.query() を使用してクエリを実行します。最後に connection.end() を使用して接続を終了します。

Nodejsのグローバル変数とは何ですか Nodejsのグローバル変数とは何ですか Apr 21, 2024 am 04:54 AM

Node.js には次のグローバル変数が存在します。 グローバル オブジェクト: グローバル コア モジュール: プロセス、コンソール、require ランタイム環境変数: __dirname、__filename、__line、__column 定数: unknown、null、NaN、Infinity、-Infinity

Nodejs インストール ディレクトリ内の npm ファイルと npm.cmd ファイルの違いは何ですか? Nodejs インストール ディレクトリ内の npm ファイルと npm.cmd ファイルの違いは何ですか? Apr 21, 2024 am 05:18 AM

Node.js インストール ディレクトリには、npm と npm.cmd という 2 つの npm 関連ファイルがあります。違いは次のとおりです。拡張子が異なります。npm は実行可能ファイルで、npm.cmd はコマンド ウィンドウのショートカットです。 Windows ユーザー: npm.cmd はコマンド プロンプトから使用できますが、npm はコマンド ラインからのみ実行できます。互換性: npm.cmd は Windows システムに固有ですが、npm はクロスプラットフォームで使用できます。使用上の推奨事項: Windows ユーザーは npm.cmd を使用し、他のオペレーティング システムは npm を使用します。

NodejsとJavaの間に大きな違いはありますか? NodejsとJavaの間に大きな違いはありますか? Apr 21, 2024 am 06:12 AM

Node.js と Java の主な違いは、設計と機能です。 イベント駆動型とスレッド駆動型: Node.js はイベント駆動型で、Java はスレッド駆動型です。シングルスレッドとマルチスレッド: Node.js はシングルスレッドのイベント ループを使用し、Java はマルチスレッド アーキテクチャを使用します。ランタイム環境: Node.js は V8 JavaScript エンジン上で実行され、Java は JVM 上で実行されます。構文: Node.js は JavaScript 構文を使用し、Java は Java 構文を使用します。目的: Node.js は I/O 集中型のタスクに適しており、Java は大規模なエンタープライズ アプリケーションに適しています。

Nodejs はバックエンド開発言語ですか? Nodejs はバックエンド開発言語ですか? Apr 21, 2024 am 05:09 AM

はい、Node.js はバックエンド開発言語です。これは、サーバー側のビジネス ロジックの処理、データベース接続の管理、API の提供などのバックエンド開発に使用されます。

NodejsとJavaのどちらを選択しますか? NodejsとJavaのどちらを選択しますか? Apr 21, 2024 am 04:40 AM

Web 開発において Node.js と Java にはそれぞれ長所と短所があり、どちらを選択するかはプロジェクトの要件によって異なります。 Node.js はリアルタイム アプリケーション、迅速な開発、マイクロサービス アーキテクチャに優れており、Java はエンタープライズ グレードのサポート、パフォーマンス、セキュリティに優れています。

See all articles