2013-09-02 3 views
22

누구나 각 동시성 메소드의 병목 현상을 설명 할 수 있습니까?멀티 프로세스 VS 멀티 스레드 서버의 이점은 무엇입니까?

서버는 유니콘 (프로세스 기반) 푸마 (스레드 기반)입니다.

각 방법이 CPU 코어를 선호합니까? 스레드? 또는 단순히 시계 속도? 또는 특별한 조합?

전용 서버를 사용할 때 필요한 최적의 CPU 특성을 결정하는 방법은 무엇입니까?

유니콘의 경우 최상의 근로자 금액을 결정하는 방법 또는 푸마의 경우 스레드 금액을 결정하는 방법은 무엇입니까?

답변

54

유니콘은 프로세스 기반입니다. 즉, 루비의 각 인스턴스는 자체 프로세스에 이어야합니다. 이는 각 프로세스에 대해 500MB의 영역에있을 수 있으므로 시스템 리소스가 빠르게 소모됩니다. 푸마는 스레드 기반이므로 이론적으로 같은 양의 동시성을 달성하기 위해 동일한 양의 메모리를 사용하지 않습니다.

유니콘은 여러 프로세스가 실행 중이므로 다른 프로세스간에 병렬 처리를 수행합니다. 이것은 CPU 코어에 의해 제한됩니다 (더 많은 코어가 동시에 더 많은 프로세스를 실행할 수 있습니다). 그러나 커널은 활성 프로세스 사이를 전환하여 4 개 또는 8 개 이상의 프로세스 (많은 코어 포함)를 실행할 수 있습니다. 기기의 메모리로 인해 제한됩니다. 최근까지 루비는 copy-on-write 방식이 아니기 때문에 모든 프로세스가 고유 한 상속 메모리 (유니콘은 프리 포킹 서버 임)를 가지고 있음을 의미했습니다. Ruby 2.0은 copy-on-write 방식으로 쓰기 쉽기 때문에 unicorn이 실제로 모든 자식 프로세스를 메모리에로드하지 않아도된다는 의미 일 수 있습니다. 나는 이것에 100 % 명확하지 않다. write on copy에 대해 읽고 jessie storimer의 멋진 책인 '유닉스 프로세스 작업'을 확인하십시오. 나는 그가 거기에서 그것을 커버했다고 확신한다.

푸마는 스레드 서버입니다. MRI 루비, 글로벌 인터프리터 잠금 (GIL) 때문에 은 한 번에 단일 CPU 바운드 작업만을 실행할 수 있습니다 (참조 : 루비 타파스 에피소드 127, 병렬 fib). 스레드 간의 컨텍스트 전환은 가능하지만 CPU 바인딩 작업 (예 : 데이터 처리) 인 한 단일 실행 스레드 만 실행합니다. 이것은 JRuby 나 Rubinius와 같이 Ruby의 다른 구현으로 서버를 실행하면 흥미로워진다. 그들은 GIL이 없으며 많은 양의 정보를 동시에 처리 할 수 ​​있습니다. JRuby는 꽤 빠르며 Rubinius는 MRI에 비해 느리지 만 다중 스레드 Rubinius는 MRI보다 빠른 속도로 데이터를 처리합니다. 그러나 비 차단 입출력 (non-blocking IO) 동안 (예 : 데이터베이스에 쓰기, 웹 요청) MRI는 비 실행 스레드로 컨텍스트 전환하고 거기에서 작업 한 다음 정보가 반환 될 때 이전 스레드로 다시 전환합니다.

유니콘의 병목 현상은 메모리 및 클럭 속도라고 말할 수 있습니다. 푸마의 경우, 병목 현상은 통역사 (MRI vs Rubinius 또는 JRuby)와 서버가 수행중인 작업 유형 (CPU 대 결속 작업 대 비 차단 IO)의 병목 현상이라고 말할 수 있습니다.

이 토론에는 엄청난 리소스가 있습니다. 이 주제에 대한 Jessie Storimer의 저서, working with ruby threadsworking with unix processes을 확인하십시오. ryan tomayko의 read this quick summary of preforking servers 및 google을 참조하십시오.

귀하의 경우 유니콘이나 퓨마에게 최선의 근로자가 얼마인지 알 수 없습니다. 가장 좋은 방법은 성능 테스트를 수행하고에 적합한 작업을 수행하는 것입니다. 아무도 맞는 크기가 없습니다.(비록 푸마 표준은 16 개의 스레드 풀을 사용하고 그것을 잠그는 것입니다.)

+0

스튜어트에게 큰 진상을 감사드립니다! – Ryan

+0

루비 2.0은 "write on write friendly"는 GC가 힙의 쓰기 페이지에서 사본과 휴지통을 공유하지 않는다는 것을 의미합니다. 1.9를 사용하면 많은 유니콘을 포크하고 GC가 실행되어 개체를 이동하고 GC 시작 전 해당 프로세스간에 발생했을 수있는 모든 COW 공유 이점을 완전히 휴지통에 버립니다. – lamont

3

푸마는 실제로 다중 스레드와 다중 프로세스입니다. MRI의 다른 코어에서 실행되는 여러 포크 작업자를 스폰하는 "클러스터 모드"로 호출 할 수 있습니다. Puma는 멀티 스레드이므로 서버의 코어 수와 동일한 수의 프로세스를 실행하는 것이 적절합니다. 이 같은 4 코어 서버 무언가가 적절할 것 같다 이처럼 :

puma -t 8:32 -w 4 --preload 

이는 최대 4 개 개의 스레드가 동시에 CPU에서 실행하는 32 개 개의 동시 스레드를 처리되고에 CPU 자원을 극대화 할 수 있어야한다 섬기는 사람. --preload 인수는 응용 프로그램을 미리로드하고 RAM 사용을 줄이기 위해 가비지 수집에 대한 ruby ​​2.0 COW 개선 사항을 이용합니다.

앱이 다른 서비스 (검색 서비스, 데이터베이스 등)를 기다리는 데 많은 시간을 소비하는 경우 크게 개선 될 것입니다. 스레드가 차단되면 동일한 프로세스의 다른 스레드가 CPU를 잡고 작업을 수행 할 수 있습니다. 이 예에서 최대 32 개의 요청을 병렬로 지원할 수 있으며 RAM에서 4 개의 프로세스 만 실행하면됩니다.

유니콘을 사용하면 32 명의 작업자를 포크해야만 RAM에서 32 개의 프로세스를 실행해야하므로 낭비가 큽니다.

모든 응용 프로그램이 CPU 크런치 인 경우 이는 매우 비효율적이며 유니콘 수를 줄여 유니온보다 푸마의 이점을 줄일 수 있습니다. 그러나 유니콘의 경우, 앱을 벤치마킹하고 올바른 숫자를 찾아야합니다. Puma는 더 많은 스레드를 생성하여 성능을 최적화하는 경향이 있으며 성능은 Unicorn (순수 CPU의 경우)에서 Unicorn (Apple의 경우 많이 사용하는 경우)보다 훨씬 뛰어납니다.

물론 Rubinius 또는 JRuby를 사용하면 해당 경연 대회가없고 멀티 코어를 실행하고 32 개의 스레드를 모두 처리하는 프로세스를 생성 할 수 있습니다.

TL; DR은 Puma가 실제로 두 모델을 모두 사용하기 때문에 Puma보다 Unicorn에 많은 이점이 있다고 생각하지 않습니다.

물론 퓨마와 유니콘의 신뢰성에 대해서는 전혀 알지 못합니다. 걱정할 필요가있는 한 가지는 한 스레드에서 전역 상태를 쓸어 넘기면 동시에 실행되는 다른 요청에 영향을 미쳐 결과가 불확실해질 수 있다는 것입니다. Unicorn은 쓰레드를 사용하지 않기 때문에 동시성 문제는 없습니다. 나는이 시간에 Puma와 Rails가 동시성 문제와 관련하여 성숙해졌으며 퓨마가 프로덕션에서 사용할 수 있었으면 좋겠다. 그러나 GitHub에서 발견 한 모든 레일즈 플러그인과 루비 젬이 threadsafe가 될 것으로 기대하지는 않을 것이고 추가 작업을해야 할 것으로 예상됩니다. 그러나 제 3 자 라이브러리에서 스레드 문제를 발견하는 데 성공하면 많은 유니콘 프로세스를 실행하는 데 드는 RAM 비용을 감당할 수 없을만큼 커질 수 있습니다. OTOH, 동시성 버그를 이해하고 Ruby를 잘 사용하기 때문에 디버깅 비용이 클라우드에서 RAM을 구입하는 비용보다 훨씬 적습니다. YMMV.

하이퍼 스레딩 된 코어 또는 실제 코어를 '-w'로 전달할 값을 계산해야하는지 잘 모르겠다면 perf 테스트를 통해 perf 테스트를 통해 사용할 값을 테스트해야합니다. -t의 경우. 필요한 프로세스 수를 두 배로 늘리는 경우에도 커널의 프로세스 스케줄러가 CPU를 포화시킬 때까지 아무 문제없이 문제를 처리 할 수 ​​있어야합니다. 어떤 경우이든 더 큰 문제가 발생할 수 있습니다. 아마도 각 하이퍼 스레드 코어 (MRI)의 프로세스를 시작하는 것이 좋습니다.

관련 문제