Nodejs의 이벤트 루프 메커니즘에 대해 자세히 알아보세요.
이 기사에서는 nodejs이벤트 루프 메커니즘을 안내합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
관련 권장 사항: "nodejs Tutorial"
Node.js는 이벤트 중심 및 비동기 I/O를 사용하여 단일 스레드, 높은 동시성 JavaScript 런타임 환경을 구현하며 단일 스레딩은 단 한 가지를 의미합니다. 그렇다면 Node.js는 단일 스레드를 통해 어떻게 높은 동시성과 비동기 I/O를 달성할 수 있을까요? 이 기사에서는 Node.js의 단일 스레드 모델을 논의하기 위해 이 문제에 중점을 둘 것입니다.
높은 동시성 전략
일반적으로 높은 동시성에 대한 솔루션은 다중 스레딩 모델을 제공하는 것입니다. 서버는 각 클라이언트 요청에 대해 스레드를 할당하고 동기식 I/O를 사용합니다. O 스레드 전환을 통한 O 호출 시간 오버헤드. 예를 들어 Apache에는 일반적으로 시간이 많이 걸리는 작업이므로 이 전략은 고성능을 달성하기 어렵지만 매우 간단하고 복잡한 상호 작용 논리를 구현할 수 있습니다.
사실 대부분의 웹사이트의 서버 측은 요청을 받은 후 처리(예: 데이터베이스 읽기)를 위해 이를 다른 서비스에 넘겨주고 결과가 반환될 때까지 기다립니다. 마지막으로 클라이언트에게 결과를 보냅니다. 따라서 Node.js는 이러한 사실을 처리하기 위해 단일 스레드 모델을 채택합니다. 각 액세스 요청에 대해 스레드를 할당하지 않고 대신 기본 스레드를 사용하여 모든 요청을 처리한 다음 I/O 작업을 비동기적으로 처리합니다. , 스레드 간 생성, 삭제 및 전환에 필요한 오버헤드와 복잡성을 방지합니다.
이벤트 루프
Node.js는 메인 스레드에 이벤트 큐를 유지합니다. 요청이 수신되면 해당 요청을 이 큐에 이벤트로 넣은 다음 계속해서 다른 요청을 받습니다. 메인 스레드가 유휴 상태일 때(액세스 요청이 없을 때) 이벤트 큐를 순환하기 시작하고 큐에 처리할 이벤트가 있는지 확인합니다. 두 가지 상황이 있습니다: I/O가 아닌 경우입니다. 함수는 I/O 작업인 경우 스레드 풀에서 스레드를 꺼내어 이벤트를 처리하고 콜백 함수를 지정한 다음 대기열의 다른 이벤트를 계속 순환합니다.
스레드의 I/O 작업이 완료되면 지정된 콜백 함수가 실행되고 완료된 이벤트는 이벤트 큐의 끝에 배치되어 메인 스레드가 이벤트로 다시 루프할 때를 기다립니다. , 직접 처리하고 상위 계층 호출로 돌아갑니다. 이 과정을 Event Loop(Event Loop)라고 하며, 그 동작 원리는 다음 그림과 같습니다.
이 그림은 전체 Node.js의 동작 원리를 왼쪽에서 오른쪽으로, 위에서부터 순서대로 나타냅니다. 하단, Node.js application 레이어, V8 엔진 레이어, Node API 레이어, LIBUV 레이어의 네 가지 레이어로 나뉩니다.
애플리케이션 레이어: JavaScript 상호 작용 레이어이며 가장 일반적인 레이어는 http, fs와 같은 Node.js 모듈입니다.
V8 엔진 레이어: V8 엔진을 사용하여 JavaScript 구문을 구문 분석한 다음 하위 API
NodeAPI 계층: 일반적으로 C 언어로 구현되는 상위 계층 모듈에 대한 시스템 호출을 제공하여 운영 체제와 상호 작용합니다.
LIBUV 레이어: 이벤트 루프, 파일 작업 등을 구현하는 크로스 플랫폼 최하위 캡슐화입니다. Node.js 비동기 구현의 핵심입니다.
Linux 플랫폼이든 Windows 플랫폼이든 Node.js는 스레드 풀을 통해 내부적으로 비동기 I/O 작업을 완료하고 LIBUV는 다양한 플랫폼의 차이점에 대한 통합 호출을 구현합니다. 따라서 Node.js의 단일 스레드는 JavaScript가 단일 스레드에서 실행된다는 의미일 뿐이며 Node.js가 단일 스레드라는 의미는 아닙니다.
작동 원리
Node.js 비동기 구현의 핵심은 이벤트입니다. 즉, 각 작업을 event로 처리한 다음 더 구체적으로 설명하기 위해 이벤트 루프를 통해 비동기 효과를 시뮬레이션합니다. 이 사실을 이해하고 받아들이기 위해 의사 코드를 사용하여 작동 원리를 설명하겠습니다.
【1】이벤트 큐 정의
큐이므로 선입선출(FIFO) 데이터 구조를 사용하여 다음과 같이 설명합니다.
/** * 定义事件队列 * 入队:push() * 出队:shift() * 空队列:length == 0 */ globalEventQueue: []
We 배열을 사용하여 대기열 구조를 시뮬레이션합니다. array 배열의 첫 번째 요소는 대기열의 선두이고, 배열의 마지막 요소는 대기열의 꼬리이며, push()는 대기열의 꼬리에 요소를 삽입하는 것입니다. Shift()는 대기열의 헤드에서 요소를 팝하는 것입니다. 이는 간단한 이벤트 큐를 구현합니다.
【2】정의 Receive 요청 항목
모든 요청은 아래와 같이 가로채서 처리 기능에 입력됩니다.
/** * 接收用户请求 * 每一个请求都会进入到该函数 * 传递参数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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Node.js는 서버측 JavaScript 런타임인 반면, Vue.js는 대화형 사용자 인터페이스를 생성하기 위한 클라이언트측 JavaScript 프레임워크입니다. Node.js는 백엔드 서비스 API 개발, 데이터 처리 등 서버 측 개발에 사용되고, Vue.js는 단일 페이지 애플리케이션, 반응형 사용자 인터페이스 등 클라이언트 측 개발에 사용됩니다.

Node.js는 고성능, 확장성, 크로스 플랫폼 지원, 풍부한 생태계, 개발 용이성 등의 기능을 제공하므로 백엔드 프레임워크로 사용할 수 있습니다.

MySQL 데이터베이스에 연결하려면 다음 단계를 따라야 합니다. mysql2 드라이버를 설치합니다. mysql2.createConnection()을 사용하여 호스트 주소, 포트, 사용자 이름, 비밀번호 및 데이터베이스 이름이 포함된 연결 개체를 만듭니다. 쿼리를 수행하려면 Connection.query()를 사용하세요. 마지막으로 Connection.end()를 사용하여 연결을 종료합니다.

Node.js에는 다음과 같은 전역 변수가 존재합니다. 전역 개체: 전역 핵심 모듈: 프로세스, 콘솔, 필수 런타임 환경 변수: __dirname, __filename, __line, __column 상수: undefine, null, NaN, Infinity, -Infinity

Node.js 설치 디렉터리에는 npm과 npm.cmd라는 두 가지 npm 관련 파일이 있습니다. 차이점은 다음과 같습니다. 확장자가 다릅니다. npm은 실행 파일이고 npm.cmd는 명령 창 바로 가기입니다. Windows 사용자: npm.cmd는 명령 프롬프트에서 사용할 수 있으며, npm은 명령줄에서만 실행할 수 있습니다. 호환성: npm.cmd는 Windows 시스템에만 해당되며 npm은 크로스 플랫폼에서 사용할 수 있습니다. 사용 권장사항: Windows 사용자는 npm.cmd를 사용하고, 기타 운영 체제는 npm을 사용합니다.

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는 대규모 엔터프라이즈 애플리케이션에 적합합니다.

예, Node.js는 백엔드 개발 언어입니다. 서버 측 비즈니스 로직 처리, 데이터베이스 연결 관리, API 제공 등 백엔드 개발에 사용됩니다.

Node.js 프로젝트의 서버 배포 단계: 배포 환경 준비: 서버 액세스 권한 획득, Node.js 설치, Git 저장소 설정. 애플리케이션 빌드: npm run build를 사용하여 배포 가능한 코드와 종속성을 생성합니다. Git 또는 파일 전송 프로토콜을 통해 서버에 코드를 업로드합니다. 종속성 설치: SSH를 서버에 연결하고 npm install을 사용하여 애플리케이션 종속성을 설치합니다. 애플리케이션 시작: node index.js와 같은 명령을 사용하여 애플리케이션을 시작하거나 pm2와 같은 프로세스 관리자를 사용합니다. 역방향 프록시 구성(선택 사항): Nginx 또는 Apache와 같은 역방향 프록시를 사용하여 트래픽을 애플리케이션으로 라우팅합니다.
