개발관련/other

일반적으로 Node.js에서 10,000 개의 동시 요청을 처리하는 방법

Rateye 2021. 10. 7. 10:53
728x90
반응형
질문 : 일반적으로 Node.js는 10,000 개의 동시 요청을 어떻게 처리합니까?

Node.js는 단일 스레드와 이벤트 루프를 사용하여 한 번에 하나씩 만 처리하는 요청 (비 차단)을 처리한다는 것을 이해합니다. 그러나 여전히 작동 원리는 10,000 개의 동시 요청이라고 가정합니다. 이벤트 루프는 모든 요청을 처리합니까? 너무 오래 걸리지 않습니까?

다중 스레드 웹 서버보다 더 빠를 수있는 방법을 (아직) 이해할 수 없습니다. 다중 스레드 웹 서버가 리소스 (메모리, CPU)에서 더 비싸다는 것을 이해하지만 여전히 더 빠르지 않습니까? 나는 아마 틀렸다. 이 단일 스레드가 많은 요청에서 더 빠른 방법과 10,000과 같은 많은 요청을 처리 할 때 일반적으로 수행하는 작업 (높은 수준)을 설명하십시오.

또한 그 단일 스레드가 그 많은 양으로 잘 확장 될까요? Node.js를 배우기 시작했다는 점을 명심하십시오.

답변

이 질문을해야한다면 대부분의 웹 애플리케이션 / 서비스가하는 일에 익숙하지 않을 것입니다. 당신은 아마 모든 소프트웨어가 이렇게한다고 생각할 것입니다.

user do an action
       │
       v
 application start processing action
   └──> loop ...
          └──> busy processing
 end loop
   └──> send result to user

그러나 이것은 웹 응용 프로그램이나 실제로 데이터베이스를 백엔드로 사용하는 모든 응용 프로그램이 작동하는 방식이 아닙니다. 웹 앱은 다음을 수행합니다.

user do an action
       │
       v
 application start processing action
   └──> make database request
          └──> do nothing until request completes
 request complete
   └──> send result to user

이 시나리오에서 소프트웨어는 데이터베이스가 반환 될 때까지 대기하는 CPU 시간 0 %를 사용하여 대부분의 실행 시간을 소비합니다.

멀티스레드 네트워크 앱:

다중 스레드 네트워크 앱은 다음과 같이 위의 워크로드를 처리합니다.

request ──> spawn thread
              └──> wait for database request
                     └──> answer request
request ──> spawn thread
              └──> wait for database request
                     └──> answer request
request ──> spawn thread
              └──> wait for database request
                     └──> answer request

따라서 스레드는 데이터베이스가 데이터를 반환 할 때까지 CPU 0 %를 사용하여 대부분의 시간을 보냅니다. 그렇게하는 동안 각 스레드에 대해 완전히 분리 된 프로그램 스택을 포함하는 스레드에 필요한 메모리를 할당해야했습니다. 또한 전체 프로세스를 시작하는 것만 큼 비싸지 않은 스레드를 시작해야합니다. 싼.

단일 스레드 이벤트 루프

대부분의 시간을 0 % CPU를 사용하기 때문에 CPU를 사용하지 않을 때 일부 코드를 실행하는 것은 어떻습니까? 이렇게하면 각 요청이 다중 스레드 애플리케이션과 동일한 양의 CPU 시간을 얻지 만 스레드를 시작할 필요가 없습니다. 그래서 우리는 이렇게합니다 :

request ──> make database request
request ──> make database request
request ──> make database request
database request complete ──> send response
database request complete ──> send response
database request complete ──> send response

실제로 두 방법 모두 처리를 지배하는 데이터베이스 응답 시간이기 때문에 거의 동일한 지연 시간으로 데이터를 반환합니다.

여기서 가장 큰 장점은 새 스레드를 생성 할 필요가 없으므로 속도를 늦출 수있는 malloc을 많이 수행 할 필요가 없다는 것입니다.

 

마법, 보이지 않는 실타래

겉보기에 신비스러워 보이는 것은 위의 두 가지 접근 방식이 "병렬"로 워크로드를 실행하는 방법입니다. 대답은 데이터베이스가 스레드된다는 것입니다. 따라서 우리의 단일 스레드 앱은 실제로 다른 프로세스 인 데이터베이스의 다중 스레드 동작을 활용합니다.

 

단일 스레드 접근 방식이 실패할 경우

데이터를 반환하기 전에 많은 CPU 계산을 수행해야하는 경우 단일 스레드 앱이 크게 실패합니다. 이제 데이터베이스 결과를 처리하는 for 루프를 의미하지는 않습니다. 그것은 여전히 대부분 O (n)입니다. 내 말은 푸리에 변환 (예 : mp3 인코딩), 레이 트레이싱 (3D 렌더링) 등과 같은 것입니다.

단일 스레드 앱의 또 다른 함정은 단일 CPU 코어 만 사용한다는 것입니다. 따라서 쿼드 코어 서버 (요즘에는 드물지 않음)가있는 경우 다른 3 개의 코어를 사용하지 않습니다.

 

다중 스레드 접근 방식이 실패한 경우

스레드 당 많은 RAM을 할당해야하는 경우 다중 스레드 앱이 크게 실패합니다. 첫째, RAM 사용량 자체는 단일 스레드 앱만큼 많은 요청을 처리 할 수 없음을 의미합니다. 더 나쁜 것은 malloc이 느립니다. 많은 객체를 할당하면 (최신 웹 프레임 워크에서 일반적으로 사용됨) 단일 스레드 앱보다 느려질 수 있습니다. 이것은 node.js가 일반적으로이기는 곳입니다.

다중 스레드를 악화시키는 한 가지 사용 사례는 스레드에서 다른 스크립팅 언어를 실행해야하는 경우입니다. 먼저 일반적으로 해당 언어에 대한 전체 런타임을 malloc해야 한 다음 스크립트에서 사용하는 변수를 malloc해야합니다.

따라서 C 또는 go 또는 java로 네트워크 앱을 작성하는 경우 스레딩 오버 헤드는 일반적으로 그리 나쁘지 않습니다. PHP 또는 Ruby를 제공하기 위해 C 웹 서버를 작성하는 경우 javascript, Ruby 또는 Python으로 더 빠른 서버를 작성하는 것은 매우 쉽습니다.

 

하이브리드 접근법

일부 웹 서버는 하이브리드 접근 방식을 사용합니다. 예를 들어 Nginx와 Apache2는 네트워크 처리 코드를 이벤트 루프의 스레드 풀로 구현합니다. 각 스레드는 단일 스레드 요청을 동시에 처리하는 이벤트 루프를 실행하지만 요청은 여러 스레드간에로드 밸런싱됩니다.

일부 단일 스레드 아키텍처도 하이브리드 접근 방식을 사용합니다. 단일 프로세스에서 여러 스레드를 시작하는 대신 여러 응용 프로그램을 시작할 수 있습니다 (예 : 쿼드 코어 시스템에서 4 개의 node.js 서버). 그런 다음로드 밸런서를 사용하여 프로세스간에 워크로드를 분산합니다.

실제로 두 가지 접근 방식은 기술적으로 서로 동일한 미러 이미지입니다.

출처 : https://stackoverflow.com/questions/34855352/how-in-general-does-node-js-handle-10-000-concurrent-requests
728x90
반응형