열린 생각
시스템의 일부가 다른 언어로 더 잘 사용될 것이라는 결론을 어떻게 얻었습니까? 성능 문제가 있습니까? 그 문제는 얼마나 심각합니까? 더 빠를 수 있다면 더 빠를 필요가 있습니까?
단일 스레드 비동기
단일 스레드 비동기 및 다중 스레드 동시성의 차이점, 장단점을 이미 다루는 몇 가지 질문과 기타 웹 리소스가 있습니다. I / O가 주요 병목 현상 일 때 Node.js의 단일 스레드 비동기 모델이 어떻게 수행되고 한 번에 많은 요청이 처리 되는지에 대해 흥미 롭습니다 .
트위스트, 토네이도 및 기타 비동기 모델은 단일 스레드를 잘 활용합니다. 많은 웹 프로그래밍에는 많은 I / O (네트워크, 데이터베이스 등)가 있으므로 원격 호출을 기다리는 데 소요되는 시간이 크게 늘어납니다. 이제 다른 데이터베이스 호출 시작, 페이지 렌더링 및 데이터 생성과 같은 다른 작업을 수행 할 수있는 시간입니다. 해당 단일 스레드의 활용도가 매우 높습니다.
단일 스레드 비동기의 가장 큰 장점 중 하나는 훨씬 적은 메모리를 사용한다는 것 입니다. 다중 스레드 실행에서 각 스레드에는 일정량의 예약 된 메모리가 필요합니다. 스레드 수가 증가함에 따라 스레드가 존재하는 데 필요한 메모리 양도 늘어납니다. 메모리는 유한하기 때문에 한 번에 만들 수있는 스레드 수에 한계가 있음을 의미합니다.
예
웹 서버의 경우 각 요청에 고유 한 스레드가 있다고 가정하십시오. 각 스레드에 1MB의 메모리가 필요하고 웹 서버에 2GB의 RAM이 있다고 가정하십시오. 이 웹 서버는 더 이상 처리 할 메모리가 부족하기 전에 어느 시점에서든 약 2000 개의 요청을 처리 할 수 있습니다.
부하가 이보다 훨씬 높으면 요청이 오래 걸리거나 (오래된 요청이 완료되기를 기다리는 경우) 가능한 동시 요청 수를 확장하기 위해 더 많은 서버를 클러스터에 던져야합니다. .
다중 스레드 동시성
멀티 스레드 동시성은 대신 여러 작업을 동시에 실행하는 데 의존합니다. 즉, 스레드가 데이터베이스 호출을 반환하기 위해 대기하는 것을 차단하면 다른 요청을 동시에 처리 할 수 있습니다. 스레드 사용률은 낮지 만 실행하는 스레드 수는 훨씬 큽니다.
멀티 스레드 코드도 추론하기가 훨씬 어렵습니다. 잠금, 동기화 및 기타 재미있는 동시성 문제와 관련된 문제가 있습니다. 단일 스레드 비동기는 동일한 문제를 겪지 않습니다.
그러나 멀티 스레드 코드는 CPU를 많이 사용하는 작업에서 훨씬 더 성능이 좋습니다. 일반적으로 차단되는 네트워크 호출과 같이 스레드가“수율”할 기회가없는 경우 단일 스레드 모델은 동시성이 없습니다.
둘 다 공존 할 수있다
물론 둘 사이에는 겹치는 부분이 있습니다. 그들은 상호 배타적이지 않습니다. 예를 들어, 멀티 스레드 코드는 각 스레드를보다 잘 활용하기 위해 비 차단 방식으로 작성 될 수 있습니다.
결론
고려해야 할 다른 많은 문제가 있지만 다음과 같이 두 가지에 대해 생각하고 싶습니다.
- 프로그램이 I / O 바운드 인 경우 단일 스레드 비동기가 아마도 잘 작동 할 것입니다.
- 프로그램이 CPU 바운드 인 경우 멀티 스레드 시스템이 가장 좋습니다.
특정한 경우에는 어떤 종류의 비동기 작업이 완료되는지와 이러한 작업이 얼마나 자주 발생하는지 확인해야합니다.
- 그들은 모든 요청에 발생합니까? 그렇다면 요청 수가 증가함에 따라 메모리가 문제가 될 수 있습니다.
- 이러한 작업은 주문 되었습니까? 그렇다면 여러 스레드를 사용하는 경우 동기화를 고려해야합니다.
- 이러한 작업은 CPU를 많이 사용합니까? 그렇다면 단일 스레드가로드를 유지할 수 있습니까?
간단한 대답이 없습니다. 사용 사례를 고려하고 그에 따라 디자인해야합니다. 때때로 비동기 단일 스레드 모델이 더 좋습니다. 다른 경우에는 대규모 병렬 처리를 위해 많은 스레드를 사용해야합니다.
다른 고려 사항
선택한 동시성 모델이 아니라 고려해야 할 다른 문제가 있습니다. Erlang 또는 Clojure를 알고 있습니까? 애플리케이션의 성능을 향상시키기 위해 이러한 언어 중 하나로 안전한 멀티 스레드 코드를 작성할 수 있다고 생각하십니까? 이 언어들 중 하나의 언어를 배우는 데 시간이 오래 걸리고, 배우는 언어가 미래에 도움이 될 것입니까?
이 두 시스템 간의 통신과 관련된 어려움은 어떻습니까? 두 개의 개별 시스템을 병렬로 유지 관리하는 것이 지나치게 복잡합니까? Erlang 시스템은 어떻게 Django로부터 작업을 받습니까? Erlang은 이러한 결과를 어떻게 Django로 다시 전달합니까? 추가 된 복잡성이 그만한 가치가있는 성능만큼 중요한 문제입니까?
마지막 생각들
나는 항상 Django가 충분히 빠르다는 것을 알고 있었고, 매우 많은 인신 매매 사이트에서 사용되었습니다. 동시 요청 수와 응답 시간을 늘리기 위해 수행 할 수있는 몇 가지 성능 최적화가 있습니다. 분명히, 나는 지금까지 Celery로 아무것도하지 않았으므로 일반적인 성능 최적화는 아마도 이러한 비동기 작업에서 발생할 수있는 문제를 해결하지 못할 것입니다.
물론 문제에 더 많은 하드웨어를 던질 것을 제안하는 것이 항상 있습니다. 새로운 서버를 구축하는 비용이 완전히 새로운 서브 시스템의 개발 및 유지 보수 비용보다 저렴합니까?
나는이 시점에서 너무 많은 질문을했지만 그것은 나의 의도였다. 분석과 세부 사항 없이는 답이 쉽지 않을 것입니다. 문제를 분석 할 수 있다는 것은 물어볼 질문을 아는 것입니다.
내 직감은 다른 언어로 다시 쓰지 않아도된다고 말합니다. 복잡성과 비용이 너무 클 것입니다.
편집하다
후속 조치
후속 조치는 매우 흥미로운 사용 사례를 보여줍니다.
1. 장고는 HTTP 요청 외부에서 작업
첫 번째 예는 NFC 태그를 읽은 다음 데이터베이스를 쿼리하는 것입니다. 이 부분을 다른 언어로 작성하는 것이 데이터베이스 나 LDAP 서버에 대한 쿼리가 네트워크 I / O (및 잠재적 인 데이터베이스 성능)에 의해 제한 될 것이기 때문에 유용하다고 생각하지 않습니다. 반면에 각 관리 명령이 자체 프로세스로 실행되므로 동시 요청 수는 서버 자체에 의해 바인드됩니다. 이미 실행중인 프로세스에 메시지를 보내지 않기 때문에 성능에 영향을주는 설정 및 해제 시간이 있습니다. 그러나 각 요청이 분리 된 프로세스이므로 동시에 여러 요청을 보낼 수 있습니다.
이 경우 조사 할 수있는 두 가지 방법이 있습니다.
- 데이터베이스가 연결 풀링을 사용하여 한 번에 여러 쿼리를 처리 할 수 있는지 확인하십시오. 예를 들어, Oracle은 Django를 적절히 구성해야합니다
'OPTIONS': {'threaded':True}
. 데이터베이스 레벨 또는 Django 레벨에는 자체 데이터베이스에 맞게 조정할 수있는 유사한 구성 옵션이있을 수 있습니다. 데이터베이스 쿼리를 작성하는 언어에 관계없이이 데이터가 반환 될 때까지 기다려야 LED를 켤 수 있습니다. 쿼리 코드의 성능은 차이를 만들 수 있으며 Django ORM은 번개가 빠르지 않지만 일반적으로 충분히 빠릅니다.
- 설정 / 삭제 시간을 최소화하십시오. 지속적으로 프로세스를 실행하고 메시지를 보냅니다. (내가 틀렸다면 나를 고치십시오.하지만 이것이 원래의 질문에 실제로 초점을 맞추고 있습니다.)이 프로세스가 Python / Django로 작성되었는지 아니면 다른 언어 / 프레임 워크로 작성되었는지는 위에 설명되어 있습니다. 관리 명령을 너무 자주 사용한다는 생각이 마음에 들지 않습니다. NFC 리더의 메시지를 메시지 큐로 푸시하는 작은 코드 조각을 지속적으로 실행할 수 있습니까? Celery는이를 읽고 Django로 전달합니다. 작은 프로그램이 파이썬으로 작성 되었더라도 (Django!는 아님) 작은 프로그램의 설정 및 해제는 Django 프로그램을 시작하고 중지하는 것 (모든 서브 시스템이있는 것)보다 낫습니다.
Django에 어떤 웹 서버를 사용하고 있는지 잘 모르겠습니다. mod_wsgi
Apache의 경우 서비스를 요청하는 프로세스 내의 프로세스 및 스레드 수를 구성 할 수 있습니다. 서비스 가능한 요청 수를 최적화하려면 웹 서버의 관련 구성을 조정해야합니다.
2. Django 신호를 이용한“메시지 전달”
두 번째 사용 사례도 상당히 흥미 롭습니다. 그것에 대한 답변이 있는지 확실하지 않습니다. 모델 인스턴스를 삭제하고 나중에 작업하려는 JSON.dumps
경우 직렬화 한 다음 역 직렬화 할 수 있습니다 JSON.loads
. 데이터베이스에서 관련 필드가 느리게로드되고 해당 링크가 더 이상 존재하지 않기 때문에 나중에 관련 그래프 쿼리 (객체 관련 모델 쿼리)를 완전히 다시 생성 할 수 없습니다.
다른 옵션은 객체를 삭제 대상으로 표시 하고 요청 / 응답주기가 끝날 때만 (모든 신호가 서비스 된 후) 객체를 삭제하는 것입니다. 에 의존하지 않고이를 구현하기 위해 사용자 정의 신호가 필요할 수 있습니다 post_delete
.