최상의 답변
질문에 대한 대답은 “하나의 스레드”의 차이와 동일합니다. “및”다 “.
하지만 실제로 의미하는 바는 다음과 같습니다. 단일 프로세스의 단일 스레드 프로그래밍에 대한 프로그래밍 방법론이 단일 스레드의 다중 스레드와 어떻게 다른지 프로세스?
주제에 대한 책이 저술되었습니다. 그러나 간단히 말해서 차이점은 모두 한 가지 요인과 관련이 있습니다. 단일 스레드 및 프로세스에서 프로그래밍 할 때 항상 현재 명령에 도달 한 방법을 알고 있습니다. 지침은 단일 순서로 발생합니다. 그러나 많은 스레드에 대해 프로그래밍 할 때 현재 명령에 도달하기 위해 어떤 명령이 어떤 순서로 실행되었는지 알 수 없습니다. 이것은 프로그래밍을 더 복잡하게 만듭니다.
그러나 그것을 복잡하게 만드는 또 다른 요소가 있습니다. 프로세스와 달리 스레드는 메모리를 공유합니다. 어떤 종류의 “동기화”가 없다면 어떤 스레드가 마지막으로 주어진 메모리 위치에 닿았는지 또는 다음 스레드가 될 것인지 알 수 없습니다. 따라서 Java의 “synchronized”키워드 (Ada에서 추출) 모니터, 세마포어, 잠금 , 조건 변수 및 메시지 전달까지 모두 동기화에 사용되었습니다.
Answer
(업데이트 : 단일 스레드 웹 서버를 가질 수 없다는 또 다른 답변을주의하십시오. 이는 사실이 아니기 때문에 동시 요청을 잘 처리합니다.)
멀티 스레드 웹 서버가 단일 스레드 서버보다 나은 이유는 무엇입니까? 아니요.
웹 서버가 동시성을 처리하는 방법에는 네 가지 기본 방법이 있습니다.
- 포킹 요청 당 OS 프로세스 (예 : Apache의 구 버전)
- 요청 당 OS 스레드 생성 (예 : Apache의 새 버전)
- 단일 스레드 이벤트 루프 (예 : nginx )
- 녹색 스레드 또는 간단한 프로세스 사용 OS 대신 VM 런타임에 의해 예약 됨 (예 : Erlang)
현재 가장 일반적인 접근 방식은 2 번과 3 번입니다.
둘 다 장단점이 있습니다. 그들의. I / O 바인딩 작업 (일반 웹 서버의 특성)의 경우 더 나은 성능
을 얻을 수 있습니다. span> 및 더 많은 동시 요청 수 는 단일 스레드 이벤트 루프 를 사용하는 경우입니다. 그러나 단점은 모든 작업에 대해 독점적으로 비동기식 비 차단 I / O를 사용해야한다는 것입니다. 그렇지 않으면 이벤트 루프를 차단하고 성능을 잃게됩니다. 따라서 멀티 스레드 서버를 구현하는 것이 더 쉽지만 성능은 지불합니다.
CPU 바인딩 작업의 경우 ( 일반적인 웹 서버, 계산 집약적 인 API에 더 일반적 일 수 있음) 코어 당 하나의 OS 스레드 또는 프로세스 를 사용하는 것이 가장 좋습니다. 단일 스레드 이벤트 루프를 사용하면 코어 당 하나의 여러 프로세스 클러스터를 실행할 수 있으므로 쉽게 수행 할 수 있습니다. 스레드 생성이 동시 요청을 처리하는 유일한 방법이라면 요청 수를 제어하지 않기 때문에 실제로 보유 할 스레드 수를 제어 할 수 없기 때문에 다중 스레드 서버를 사용하는 것은 어렵습니다. CPU 코어 수보다 많은 스레드가 있으면 컨텍스트 스위치 의 성능이 저하되고 RAM도 많이 사용됩니다.
이것이 단일 스레드 nginx 서버 가 다중 스레드 Apache 웹 서버보다 더 나은 성능을 발휘하는 이유입니다 (그리고 nginx가 처음에 만들어진 이유입니다). 또한 뛰어난 성능으로 알려진 데이터베이스 인 Redis 는 단일 스레드 입니다.
제가 제공 할 수있는 실제 예는 다음과 같습니다. 첫 번째 웹 서버는 500MB RAM이 장착 된 Linux 시스템에서 실행되는 Apache였습니다. 모든 요청에 대해 새로운 프로세스를 포크했습니다 (실제로 풀이 있으므로 포크가 많지 않았지만 이러한 프로세스를 계속 유지하여 재사용하고 리소스 유출을 방지하기 위해 가끔 죽여야했습니다).
내 OS는 약 100MB의 RAM을 사용했습니다. 모든 Apache 프로세스는 20MB의 RAM을 사용했습니다. 내 서버는 20 개의 동시 요청 만 처리 할 수 있었고 더 이상 RAM이 없기 때문에 해결할 방법이 없었습니다. 프로세스는 대부분 I / O에서 차단되었으므로 CPU 사용률이 매우 낮았으며 20 개를 초과하는 모든 요청은 기다려야했습니다. 오래 실행되는 다운로드에서 내 서버는 완전히 응답하지 않았습니다.
nginx 웹 서버가 도입되었을 때 단일 스레드 이벤트 루프를 사용했으며 요청을 차단하지 않았습니다. 신화적인 c10k 문제는 문제없이 훨씬 더 많은 동시 요청을 처리 할 수 있습니다. nginx는 기본적으로 c10k 문제 (10,000 개의 동시 요청)를 해결하기 위해 만들어졌습니다.
만약 스레드 10,000 개에 낭비되는 RAM의 양을 상상해보십시오. 컨텍스트 전환에 사용되는 시간과 그 수를 생성 할 수도 있습니다.
다중 스레드 Apache와 단일 스레드 nginx의 메모리 사용량 :
이것이 Ryan Dahl이 Node.js에서 비 차단 I / O와 단일 스레드 이벤트 루프를 사용하고 Deno에서 여전히 동일한 아이디어를 사용하는 이유입니다. 이것이 고성능 네트워크 서버를 작성하는 방법이기 때문입니다 (여기에있는 다른 답변에서 읽을 수있는 것과 반대).