이 글은 파이썬 세계에서 나온 것이지만, 여전히 전체 프로그래밍 분야에 적용할 수 있습니다. 멀티스레딩으로 요청을 더 빠르게 처리할 수 있지만, 한계가 있습니다. 그린(마이크로스레드) 스레드가 해결책입니다.
멀티스레드 소프트웨어 개발은 특히 사용자 반응을 빠르게 하기 위해 요구가 높은 성능을 요구하는 네트워크 중심 애플리케이션에서 많은 문제를 해결합니다. 안타깝게도 멀티스레딩만으로는 대규모 문제를 해결하기에 충분하지 않습니다동시성성적인 문제들.
이러한 문제를 해결하려면 비동기 이벤트와 콜백 기반 메커니즘을 사용하는 프로그래밍 모델을 변경해야 합니다. Druva에서는 대규모 문제를 해결하기 위해 Dhaga라는 파이썬 기반 라이브러리를 만들었습니다동시성프로그래밍 모델은 큰 변경이 필요하지 않습니다.
소프트웨어 개발자들은 한 곳에서 생활합니다동시성세상. 스레드는 오늘날 특히 개발 중, 특히 Druva와 같은 inSync 시스템(네트워크 보안 동기화 제품)처럼 집중적인 네트워크 작업을 수행할 때 매우 중요합니다. 멀티스레딩은 네트워크 작업을 위한 프로그래밍 코드의 흐름을 간단하고 질서 있게 만듭니다. 애플리케이션이 성능 향상이나 개선이 필요할 때는 개선할 수 있습니다탄성, 스레드 수를 늘릴 수 있습니다.
하지만 수천 개의 스케일에 관해서는동시성요청이나 스레드만으로는 부족합니다.
멀티스레딩에는 다음과 같은 단점이 있다는 것을 발견했습니다: 1. inSync 시스템 클라이언트는 네트워크 RPC 호출을 통해 많은 파일을 서버에 백업해야 합니다. 개발자들이 속도를 높이는 일반적인 방법은 스레드를 사용하는 것입니다. 하지만 멀티스레딩이 제공하는 성능은 메모리와 CPU 비용을 증가시킵니다; 개발자들은 속도와 스레드 수 사이의 균형을 유지해야 합니다.
2. 우리 서버는 inSync 시스템과 수천 명의 고객 간 통신을 담당해야 합니다동시성연결과 알림. 연결을 효율적으로 처리하기 위해 우리는 요청을 처리하는 데 스레드를 사용합니다. 하지만 inSync 시스템 고객 수가 늘어나면서 스레드 수를 계속 늘려야 하며, 이는 서버 메모리와 CPU를 많이 소모합니다.
3. 우리 웹 서버는 수천 건의 병렬 HTTP 요청을 처리해야 합니다. 대부분의 작업은 데이터를 받고 보내고 inSync 시스템의 백엔드로 전달하는 네트워크 소켓에 집중됩니다. 대부분의 스레드가 네트워크 작업을 기다리게 만듭니다. C10K 문제를 일으키는 원인은, 웹 서버에 수천 건의 동기식 요청이 있을 때 각 요청마다 스레드를 생성하는 것이 매우 확장성이 떨어진다는 것입니다(Scale).
비동기 프레임워크의 한계 Twisted, Tornado Tornado, asyncore 등 많은 비동기 프레임워크는 개발자들이 인기 있는 스레드 사용 방식에서 벗어나는 데 도움을 줄 수 있습니다. 이 프레임워크들은 비차단 소켓과 콜백 메커니즘(Node.js과 유사)에 의존합니다. 이 프레임워크를 그대로 사용하면 Druva 코드의 주요 부분을 리팩토링해야 할 것입니다. 그게 우리가 원하는 게 아니야. 코드를 리팩토링하면 개발 및 테스트 주기가 늘어나고, 이는 확장 요구사항을 충족하지 못하게 만듭니다. 제품의 여러 부분이 방대해야 하기 때문에, 우리 각자가 이를 재구성해야 하므로 두 배, 세 배로 만드는 노력이 필요합니다.
코드를 너무 많이 바꾸지 않기 위해 기존 프레임워크를 직접 사용하는 것에서 벗어나야 했습니다. 다행히도 유용한 도구들을 찾았습니다.
네트워크 I/O에서 코드 실행을 제어하고 싶기 때문에, 스레드를 마이크로 스레드로 나누는 방법이 필요합니다. 우리는 다음을 찾는다그린렛츠。 이 프로그램은 코루틴 코루틴이라 불리는 암묵적 마이크로스레드 스케줄링을 제공합니다. 다시 말해, 코드를 제어하고 싶을 때 유용합니다. 그린렛 수확 정지 시간을 조절할 수 있기 때문에 맞춤형 스케줄을 위한 마이크로스레드를 만들 수 있습니다. 이것은 저희에게 완벽한 방법으로, 코드 스케줄링을 완전히 제어할 수 있게 해줍니다.
토네이도는 수천 건의 비동기 요청을 처리하도록 파이썬으로 작성된 단순하고 차단되지 않는 웹 서버 프레임워크입니다. 우리는 그 핵심 구성 요소인 IOLoop IOStream을 사용합니다. IOLoop은 차단하지 않는 소켓 I/O 이벤트 루프입니다; 리눅스에서는 epoll을 사용하거나 BSD와 Mac OS X에서는 큐를 사용하며, 그렇지 않으면 윈도우에서는 선택이 가능하다면 선택합니다. IOStream은 읽기 및 쓰기를 위한 편리한 패키징과 같은 차단 방지 소켓을 제공합니다. 모든 소켓 작업을 Tornado에 위임하고, 콜백을 사용해 코드 작업을 완료하도록 트리거합니다(banq note: Node.js 메커니즘과 매우 유사합니다).
좋은 시작이지만, 더 많은 것이 필요합니다. 위 모듈을 코드에 직접 사용하면 RPC 코드의 많은 부분을 변경해야 합니다. 예를 들어, 그린렛을 통한 RPC 스케줄링, 그린렛이 막히지 않도록 (그린렛이 막히면 스레드 전체와 다른 모든 스레드가 막히게 됨), 토네이도의 콜백 함수 처리가 필요합니다.
외부 호출로 인해 그린렛이 복잡해지지 않도록 관리하고 배열할 추상화가 필요하며, 이 추상화는 스레드를 넘어 대규모로 확장될 수 있습니다. 이 추상화가 바로 Dhaga로, 애플리케이션 코드 흐름을 전통적인 동기식 시퀀스처럼 프로그래밍할 수 있게 하지만, 실행은 비동기적입니다.
Dhaga(힌디어로 스레드를 의미함)는 우리가 추상화한 가벼운 스레드를 위한 실행 프레임워크입니다. Dhaga 클래스는 greenlets에서 파생되었으며, 단일 운영 체제 스레드에서 여러 코드 흐름을 실행하기 위해 스택 스위칭을 사용합니다. 한 운영체제의 스레드는 협업 스케줄링을 사용하여 여러 dhagas를 실행합니다. dhaga가 대기할 때(주로 RPC 호출이 돌아오기를 기다리는 동안), 부모 레벨(즉, 이를 생성한 OS 레벨 스레드의 실행 컨텍스트)에 제어권을 넘깁니다. 그 후 부모 레벨은 또 다른 다가를 실행할 준비를 합니다. RPC 호출은 토네이도 웹 서버에 전달되어 소켓을 비동기적으로 작성하게 되고, 콜백이 돌아오면 콜백이 등록됩니다. 이 RPC가 돌아오면 대기 중인 다가가 실행 큐에 추가되고 부모 스레드가 이를 받습니다. (방크 노트: node.js 원리와 유사함)
지연 시간이 많은 작업에서는 스레드 대신 Dhaga를 사용할 수 있고, 스레드 수가 합리적인 처리량 한도를 초과할 때는 단일 스레드에 512개의 dhaga를 사용합니다.
|