2011-08-15 2 views
35

랙에서 동시 요청 처리 옵션을 완전히 이해하려고합니다. 나는 long-polling 앱을 만들기 위해 async_sinatra를 사용했으며, 이제 throw :async 및/또는 Thin-threaded 플래그를 사용하여 베어 메탈 랙을 실험하고 있습니다. 나는 그 주제에 만족하지만, 나는 단지 이해할 수없는 것들이있다. (아니요, 병렬성에 대한 동시성을 오해하지 않고 있습니다. 예, GIL이 부과 한 한계를 이해하고 있습니다.)랙 동시성 - rack.multithread, async.callback 또는 둘 다?

Q1. 테스트 결과 thin --threaded (즉 rack.multithread=true)은 별도의 스레드 (EM 사용을 전제로 함)로 동시에 요청을 실행합니다. 즉, 장기 실행 요청 A는 요청 B (IO 제외)를 차단하지 않습니다. 즉, 응용 프로그램에 동시성을 얻기 위해 특별한 코딩 (예 : 콜백)이 필요하지 않습니다 (다시 DB 호출, IO 등을 차단하지 않음). 이것이 내가 관찰 한 것으로 믿는다. 맞습니까?

질문 2. 동시성을 달성하는 또 다른 방법으로는 EventMachine.deferthrow :async이 있습니다. 엄밀히 말하면, 요청은 이 아니고은 스레드를 사용하여 처리됩니다. 그들은 순차적으로 다루어 지지만, heavyly lifting과 콜백을 EventMachine으로 전달합니다. EventMachine은 async.callback을 사용하여 나중에 응답을 보냅니다. 요청 A가 작업을 EM.defer로 오프로드 한 후에 요청 B가 시작됩니다. 이것이 맞습니까?

3. 위의 내용이 정확하다고 가정하면 은 다른 방법보다 한 가지 방법에 특별한 이점이 있습니까? 분명히 --threaded은 마법의 총알처럼 보입니다. 단점이 있습니까? 그렇지 않다면 모두가 왜 async_sinatra/throw :async/async.callback에 대해 이야기하고 있습니까? 아마 이전 버전은 "나는 Rails 앱을 무거운 짐을 싣고 약간 더 부드럽게하고 싶다"는 것이고, 후자는 장기 실행 요청이 많은 앱에 더 적합할까요? 아니면 규모가 중요한 요소일까요? 그냥 여기서 추측 해.

MRI 루비 1.9.2에서 씬 1.2.11을 실행 중입니다. (epoll에 루비 1.9.2의 EventMachine의 사용과 a long-standing, supposedly-resolved-but-not-really problem을 거기로 참고로, 나는 --no-epoll 플래그를 사용해야 즉, 지점 옆에, 그러나 어떤 통찰력을 환영합니다..)

+0

epoll 문제는 해당 티켓에서 말한대로 [커밋] (https://github.com/eventmachine/eventmachine/commit/d684cc3b77a6c401295a3086b5671fe4ec335a64)으로 수정해야합니다. 나는 --no-는 epoll 플래그를 제거하면 – Bitterzoet

+0

내 스레드 요청 분에 밀리 초에서 이동합니다. EM 0.12.10, Ruby 1.9.2-p180. 나는 p290을 컴파일하려고 시도 할 수 있다고 생각합니다 ... – bioneuralnet

+0

좋은 질문입니다. 나는 비슷한 질문을 여기에 : http://stackoverflow.com/questions/8146851/how-to-deploy-a-threadsafe-asynchronous-rails-app 및 https : // github 여기 몇 가지 실험을 수행했습니다. com/jjb/threaded-rails-example (스레드 thin이 비동기식으로 성공적이지만 벤치 마크 속도가 느리다는 점에 유의하십시오) –

답변

24

참고 : 나는 모든 동의어로 얇은 사용 비동기 랙 확장을 구현하는 웹 서버 (예 : Rainbows !, Ebb, Puma의 향후 버전 ...)

Q1. 수정하십시오. 응답 생성 (call)을 EventMachine.defer { ... }에 래핑하여 EventMachine이 기본 스레드 풀에 푸시하도록합니다.

질문 2.async.callbackEM.defer과 함께 사용하면 기본적으로 스레드 풀을 사용하므로 Q1에 설명 된 것과 비슷한 구조로 끝나기 때문에 실제로는별로 의미가 없습니다. async.callback을 사용하면 IO 용 이벤트 머신 라이브러리 만 사용할 때 의미가 있습니다. Thin은 일반 랙 응답을 인수로 사용하여 env['async.callback']이 호출되면 클라이언트에 응답을 보냅니다.

본문이 EM::Deferrable 인 경우 Thin은 연기가 성공할 때까지 연결을 닫지 않습니다. 오히려 잘 알고있는 비밀 : 부분 응답 만 보낸 후 연결을 계속 유지하는 것보다 긴 폴링을 원할 경우 throw :async 또는 -1의 상태 코드를 사용하지 않고도 본체 객체로 EM::Deferrable을 직접 반환 할 수 있습니다.

3. 맞 겠지. 를 제공하는 스레드 것은 다르게 변화 랙 응용 프로그램의 부하를 향상시킬 수 있습니다. 나는 모든 코어가 사용될 수 Rubinius 또는 JRuby에서, 실행 때 20 % 더 루비 1.9.3 내 컴퓨터에 간단한시나 응용 프로그램에 대한 개선을 참조하십시오. 두 번째 접근 방식은 이벤트 방식으로 애플리케이션을 작성하는 경우 유용합니다.

랙 위에 마술과 해킹을 많이 던져서 이벤트가 발생하지 않는 응용 프로그램에서 해당 메커니즘을 사용할 수 있습니다 (em-synchrony 또는 sinatra-synchrony 참조). 그러면 디버깅 및 종속성 지옥에 남겨 둡니다. .

비동기 방식은 가장 a web chat처럼 evented 접근 방식으로 해결하는 경향이 응용 프로그램과 실제 의미가 있습니다. 그러나 모든 폴링 연결이 스레드를 차단하므로 long-polling을 구현하는 스레드 접근 방식을 사용하지 않는 것이 좋습니다. 이것은 처리 할 수없는 많은 스레드 또는 연결로 당신을 떠날 것입니다. EM의 쓰레드 풀은 기본적으로 20 개의 쓰레드 크기를 가지므로 프로세스 당 20 개의 대기 연결을 제한합니다.

들어오는 모든 연결에 대해 새 스레드를 만드는 서버를 사용할 수는 있지만 스레드를 만드는 것은 비용이 많이 듭니다. (MacRuby를 제외하고 MacRuby는 프로덕션 응용 프로그램에서 사용하지 않습니다). 예를 들면 servnet-http-server 있습니다. 원하는 것은 요청과 스레드의 n : m 매핑입니다. 그러나 거기에 서버가 없습니다.

자세한 내용은 다음을 참조하십시오. Rocky Mountain Ruby (및 다른 여러 회의)에서 이에 대한 프레젠테이션을했습니다. 비디오 녹음은 on confreaks입니다.

관련 문제