Node.js가 단일 스레드 인 이유는 무엇입니까? [닫은]


255

PHP (또는 Java / ASP.NET / Ruby) 기반 웹 서버에서 모든 클라이언트 요청은 새 스레드에서 인스턴스화됩니다. 그러나 Node.js에서 모든 클라이언트는 동일한 스레드에서 실행됩니다 (동일한 변수를 공유 할 수도 있습니다!) I / O 작업은 이벤트 기반이므로 기본 스레드 루프를 차단하지 않습니다.

내가 이해하지 못하는 것은 Node 작성자가 단일 스레드로 선택한 이유는 무엇입니까? 상황을 어렵게 만듭니다. 예를 들어, 메인 스레드를 차단하고 새로운 클라이언트 요청이 차단되므로 CPU 집약적 기능을 실행할 수 없으므로 프로세스를 생성해야합니다. 즉, 별도의 JavaScript 파일을 작성하고 다른 노드 프로세스를 실행해야합니다. 그것). 그러나 PHP에서 CPU 집중적 인 작업은 각 클라이언트가 다른 스레드에 있기 때문에 다른 클라이언트를 차단하지 않습니다. 멀티 스레드 웹 서버와 비교했을 때의 장점은 무엇입니까?

참고 :이 문제를 해결하기 위해 클러스터링을 사용했지만 그다지 좋지 않습니다.


12
나는 최근 Node의 이론에 대한 좋은 비디오 (29 분)를 보았다. 나는 심지어 남자가 CPU 집약적 인 작업에 대해 간단히 다루고 있다고 생각합니다. youtube.com/watch?v=L0pjVcIsU6A
whirlwin

24
당신은 이것을 알 수 있지만 분명히 Node.js는 단일 스레드가 아닙니다. JavaScript 코드는 단일 스레드를 실행하지만 IO 작업 및 플러그인이 스레드 풀에서 실행할 수있는 기타 작업을 실행합니다. Node.js는 멀티 스레딩 코드를 처리 할 필요없이 멀티 스레딩의 많은 이점을 제공합니다. 또한 Node.js 기고자들은 JavaScript의 단일 스레드 특성을 선택하지 않았습니다. JS가 멀티 스레드 컨텍스트에서 작동하는 방식을 생각할 수는 없지만 V8은 Node.js가 JavaScript 엔진으로 사용하는 방식으로 작성되지 않았습니다.
Brad

5
PHP는 JavaScript보다 단일 스레드입니다. 아마도 FastCGI 또는 mod_php와 같은 서버 모듈을 생각하고있을 것입니다. 따라서 Node.js를 PHP, Java 또는 Ruby가 아닌 Apache, Nginx 또는 IIS와 비교하고 있습니다.
Álvaro González

34
노드가 단일 스레드가 아닙니다. 대중적인 오해입니다. 간단한 것조차도 내 시스템에 5 개의 스레드node -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $!표시 합니다. 기본 이벤트 루프 는 단일 스레드이지만 그렇지 않은 경우에는 의미가 없습니다. 그러나 노드는 매우 다중 스레드이므로 원하는 경우 다중 스레드 단일 프로세스 응용 프로그램을 작성할 수 있습니다. 나는 그것에 대한 포괄적 인 답변을 작성하고 싶지만 어떤 사람들은 당신의 질문을 끝내기로 결정했습니다. 다시 열기로 투표하고 있습니다. 더 많은 표를 얻고 다시 열면 의견에 저를 언급하십시오.
rsp

2
@rsp 귀하의 의견에 감사드립니다. 그러나 나는 주요 스레드가 i / o와 관련이 없다는 것을 의미했습니다. 큰 for 루프와 같은 CPU 관련 작업을 수행하면 서버가 연결 처리를 중지합니다. 즉, 당시 서버를 사용할 수 없습니다. 따라서 대부분의 서버처럼 본질적으로 모든 연결을 스레딩하는 대신 클러스터와 같은 해킹을 사용하여 매우 간단한 작업을 수행합니다. jxcore.com 은이 문제를 해결하려고했지만 본질적으로 사용할 수없는 특수 / 수정 된 노드 플러그인을 사용합니다.
foreyez

답변:


292

Node.js는 비동기 처리 실험으로 명시 적으로 작성되었습니다. 이론은 단일 스레드에서 비동기 처리를 수행하면 일반적인 스레드 기반 구현보다 일반적인 웹로드에서 더 많은 성능과 확장 성을 제공 할 수 있다는 것입니다.

그리고 당신은 무엇을 알고 있습니까? 제 생각에는 이론이 널리 퍼져 있다는 것입니다. CPU를 많이 사용하지 않는 node.js 앱은 Apache 또는 IIS 또는 다른 스레드 기반 서버보다 수천 개의 동시 연결을 실행할 수 있습니다.

단일 스레드, 비동기 특성으로 인해 작업이 복잡해집니다. 그러나 솔직히 스레딩보다 더 복잡하다고 생각하십니까? 한 번의 경쟁 조건으로 한 달 내내 망치질 수 있습니다! 또는 어딘가에 설정되어 스레드 풀을 비우고 응답 시간이 느려지는 것을 지켜보십시오! 교착 상태, 우선 순위 반전 및 멀티 스레딩과 함께 제공되는 다른 모든 설명은 말할 것도 없습니다.

결국, 그것이 보편적으로 더 나쁘다고 생각하지 않습니다. 그것은 다르고 때로는 더 좋으며 때로는 그렇지 않습니다. 작업에 적합한 도구를 사용하십시오.


26
그러나 웹 서버는 일반적으로 데이터베이스를 가져 오는 것이 아니라 많은 CPU 집약적 작업을 수행합니다. 우리는 우리가 가져온 것을 처리하고 클라이언트에게 서비스를 제공하기 전에 많은 비즈니스 로직을 많은 시간을 할애해야합니다.
foreyez

22
작업자를 스폰하십시오! 이것이 Node.js와의 모든 거래입니다. 무거운 프로세스는 다른 프로세스에서 실행될 수 있으며 처리하면 가벼운 콜백이 발생합니다.
MaiaVictor

7
문제는 작업 자당 운영 체제 수준 프로세스가 실행되고 있다는 것입니다. "ps"명령을 사용하여 볼 수 있습니다. 따라서 잠재적으로 한 번에 수천 개의 프로세스가 시스템에서 실행되고 있음을 의미합니다.
foreyez

9
@foreyez, 사용자 당 프로세스가 필요하지 않습니다. 하중을 분할하는 방법을 선택할 수 있습니다. 또한 모든 사람이 많은 CPU 집약적 인 일을하는 것은 아닙니다. 노드는 직업을위한 도구입니다. 아마도 직업이 아니라 많은 종류의 직업입니다.
Brad

15
사실, @foreyez는 "웹 서버는 일반적으로 CPU 집약적 인 ALOT (sic)에 대한 웹 서버"라는 진술을 뒷받침하고 싶습니다. 내 경험으로는 그렇지 않습니다. 또는 'cpu 집약적'에 대한 나의 정의는 그의 것과 다릅니다. 제품 데이터를 UI로 변환하는 것은 CPU를 많이 사용하지 않으며 주문 등을 계산하지도 않습니다. 대부분의 웹은 매우 거래 적입니다. CPU를 많이 사용하는 것은 비디오 변환, 이미지 형식 변환 등과 같은 것입니다. 그 중 대부분은 실제로 노드가 잘 수행하는 파일 I / O 때문입니다. 또한 전환 전용 프로세스로 쉽게 오프로드 할 수 있습니다.
Paul

62

서버에 대한 "요청 당 하나의 스레드"모델의 문제점은 이벤트 루프 스레드 모델과 비교하여 여러 시나리오에서 확장 성이 좋지 않다는 것입니다.

일반적으로 I / O 집중 시나리오에서는 요청이 I / O가 완료 될 때까지 대부분의 시간을 소비합니다. 이 시간 동안 "요청 당 하나의 스레드"모델에서 스레드에 연결된 리소스 (예 : 메모리)는 사용되지 않으며 메모리가 제한 요소입니다. 이벤트 루프 모델에서 루프 스레드는 처리 할 다음 이벤트 (I / O 완료)를 선택합니다. 따라서 스레드는 항상 사용 중입니다 (물론 올바르게 프로그래밍하면).

모든 새로운 것의 이벤트 루프 모델은 빛나고 모든 문제에 대한 솔루션이지만 사용할 모델은 해결해야 할 시나리오에 따라 다릅니다. 프록시와 같은 집중적 인 I / O 시나리오가있는 경우, 이벤트 기반 모델이 지배하는 반면 동시 프로세스 수가 적은 CPU 집중 시나리오는 스레드 기반 모델에서 가장 잘 작동합니다.

현실 세계에서 대부분의 시나리오는 약간 중간에 있습니다. 정확한 아키텍처를 찾으려면 확장성에 대한 실제 요구와 개발 복잡성의 균형을 맞출 필요가 있습니다 (예 : CPU 집약적 작업을 위해 백엔드에 위임하는 이벤트 기본 프런트 엔드를 갖습니다. 프런트 엔드는 작업을 기다리는 데 거의 리소스를 사용하지 않습니다. 분산 시스템과 마찬가지로 작동하려면 약간의 노력이 필요합니다.

아무 노력없이 시나리오에 맞는 은색 총알을 찾고 있다면 발에 총알이 생깁니다.


8
Node.js는 v8 멀티 스레딩 지원이 없기 때문에 이벤트 전용 처리로 제한됩니다. Javascript 언어 자체에는 필요한 기능이 없으므로 구현이 까다로울 수 있습니다. 이것이 Node.js의 주범입니다. 제 생각에는. 다른 언어에서는 원하는 것을 선택할 수 있습니다. 또는 Java NIO와 같은 두 모델의 일부 하이브리드.
FrameGrace

2
@ Kazaag, 최신 웹 서버 스레드 풀을 유지 관리합니다. 그들은 페이지로드 당 새로운 스레드를 바보로 생성하지 않습니다. 그것들은 오래된 웹 서버입니다.
Pacerier

1
@Pacerier 새 스레드가 생성되었다고 말한 적이 없지만 요청이 완료 될 때까지 각 스레드가 하나의 요청에 할당됩니다.
Kazaag

2
@Kazaag "요청이 끝날 때까지 각 스레드가 하나의 요청에 할당된다"는 것은 일반적인 규칙이 아닙니다. 즉 .Net (HTTP 요청 처리 포함)에서는 비동기 (작업 기반) 프로그래밍을 사용할 수 있고 사용해야하며 이는 입출력 및 기타 비동기 작업이 완료되기를 기다리는 동안 스레드를 해제합니다. 이는 MVC / API 컨트롤러와 같은 고급 프로그래밍에도 적용됩니다. 따라서 실제로 20 개의 HTTP 요청이 보류 중이지만 하나의 활성 스레드 만있을 수 있습니다.
user3285954

29

간단히 말해 노드는 V8에서 가져옵니다. V8은 내부적으로 단일 스레드입니다. CPU를 많이 사용하는 작업의 제약 조건을 해결하는 방법이 있습니다.

한 시점 (0.7)에서 저자는 여러 계산 스레드를 구현하는 방법으로 분리를 도입하려고 시도했지만 결국 제거되었습니다. https://groups.google.com/forum/#!msg/nodejs/zLzuo292hX0/F7gqfUiKi2sJ


이 "격리"에 대한 자세한 정보가 있습니까?
Pacerier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.