본문 바로가기

프로그래밍

Boost::asio – Overview – Core Concepts and Functionality – The Proactor Design Pattern: Concurrency Without Threads

출처: http://www.dhsnest.com/2010/03/boostasio-overview-core-concepts-and-functionality-the-proactor-design-pattern-concurrency-without-threads/



Proactor 디자인 패턴 : 스레드 없는 동시성

 

Boost.Asio 라이브러리는 동기와 비동기 양측을 모두 지원합니다. 비동기에 대한 지원은 Proactor 디자인 패턴[POSA2]에 기반합니다. 이 방법의 장단점과 동기적 방법만 사용한 경우나 Reactor를 사용한 경우와의 비교는 아래에 있습니다.

 

Proactor와 Boost.Asio

 

플랫폼과 관련된 세부사항 없이 Proactor 디자인 패턴이 어떻게 Boost.Asio에 구현되었는지 보겠습니다.

 

 사용자 삽입 이미지

 

Proactor 디자인 패턴

 

  • Asynchronous Operation

 

소켓에서의 비동기적 읽기 또는 쓰기 같은 비동기적으로 실행되는 동작을 정의합니다

 

  • Asynchronous Operation Processor

 

비동기적 동작을 실행하고 동작이 완료될때 Completion Event Queue에 이벤트를 추가합니다. 상위 수준의 관점에서,stream_socket_service같은 서비스들이 Asynchronous Operation Processor에 해당합니다.

 

  • Completion Event Queue

 

Asynchronous event demultiplexer에 의해서 디큐잉 될때까지의 완료 이벤트들의 버퍼

 

 

  • Completion Handler

 

비동기적 동작에 대한 처리. 함수 객체들로, 종종 boost::bind로 생성됩니다.

 

  • Asynchronous Event Demultiplexer

 

Completion event queue에 이벤트가 발생할때 까지 대기를 차단하고, 호출자에게 완료된 이벤트를 반환합니다.

 

  • Proactor

 

큐에서 이벤트를 꺼내기 위해 Asynchronous event demultiplexer를 호출하고, 이벤트와 관련된 Completion handler를 디스패치(함수 객체의 실행)합니다. 이러한 추상화는 io_service 클래스로 나타납니다.

 

  • Initiator

 

응용 프로그램에 명시된 비동기적 동작의 시작 코드입니다. Initiator는 Asynchronous operation processor와 stream_socket_service같은 서비스에 delegate를 반환하는 asio::basic_stream_socket등의 상위 수준 인터페이스를 통해 상호작용 합니다.

 

Reactor를 사용한 구현

 

많은 플랫폼에서 Boost.Asio는 select, epoll 또는 kqueue 같은 Reactor를 통해 Proactor를 구현합니다. 이러한 구현은 아래와 같이 Proactor 디자인 패턴과 일치합니다:

 

  • Asynchronous Operation Processor

 

Reactor는 select, epoll 또는 kqueue를 사용해 구현됩니다. Reactor가 자원이 준비되었음을 알려주면, Processor는 비동기 동작을 실행하고, 관련된 Completion handler를 Completion event queue에 추가합니다.

 

  • Completion Event Queue

 

Completion handler(함수 객체)들의 링크드 리스트

 

 

  • Asynchronous Event Demultiplexer

 

Completion event queue에서 Completion handler가 사용 가능할때까지 이벤트나 상태 변수를 대기함으로써 구현됩니다.

 

윈도우즈 Overlapped I/O를 사용한 구현

 

윈도우즈 NT, 2000 그리고 XP에서 Overlapped I/O로 인해 Boost.Asio는 Proactor 디자인 패턴의 구현에 이점이 있습니다. 이러한 구현은 아래와 같이 Proactor 디자인 패턴과 일치합니다:

 

  • Asynchronous Operation Processor

 

운영체제에 의해 구현됩니다. AcceptEx 같은 Overlapped 함수 호출로 동작을 초기화합니다.

 

  • Completion Event Queue

 

운영체제에 의해 구현되고, I/O Completion Port와 연관되어 있습니다. 각각의 io_service 인스턴스마다 하나의 I/O Completion Port가 있습니다.

 

  • Asynchronous Event Demultiplexer

 

Boost.Asio가 이벤트나 관련된 Completion handler를 큐에서 꺼내기 위해 호출합니다.

 

장점

 

  • 이식성

 

많은 운영체제에서 고성능 네트워크 프로그램을 개발을 위한 옵션으로 네이티브 비동기 입출력 API(윈도우즈의 Overlapped I/O같은)를 제공합니다. 라이브러리는 네이티브 비동기 입출력으로 구현되었습니다. 그러나, 네이티브 수준의 구현이 불가능한 경우 POSIX의 select()같은 Reactor 패턴의 동기적 이벤트 디멀티플렉서를 사용해 구현합니다.

 

  • 동시성으로부터 스레드의 분리

 

긴 시간이 필요한 동작은 응용프로그램 대신에 라이브러리에 의해 비동기적으로 실행됩니다. 따라서, 응용프로그램에서 동시성 향상을 위해 많은 스레드를 생성할 필요가 없습니다.

 

  • 성능과 확장성

 

thread-per-connection(동기적 방법만 사용할 수 있는 경우)같은 구현 전략은 컨텍스트 스위칭, 동기화, CPU사이의 데이터 이동으로 인해 시스템 성능을 저하시킵니다. 비동기 동작을 사용 함으로써 운영체제 스레드의 수(일반적으로 제한된 자원)를 줄여 컨텍스트 스위칭 비용을 감소시키고 처리할 이벤트들을 제어하는 논리적인 스레드만 활성화 시키면 됩니다.

 

  • 단순화된 응용프로그램 동기화

 

비동기 동작 Completion handlers는 단일 스레드 환경처럼 작성될 수 있습니다. 따라서 응용프로그램 개발에서 동기화에 관련된 문제에 대한 고려가 줄어듭니다.

 

  • 함수 합성

 

함수 합성은 특정 형식의 메시지를 보내는 것 같은 상위 수준의 동작을 하는 함수의 구현에 적용됩니다. 각각의 함수는 하위 수준의 읽기 또는 쓰기 동작을 다수 호출함으로써 구현됩니다.

 

예를 들어, 바디의 길이를 담고 있는 고정된 길이의 헤더와 가변 길이의 바디로 이루어진 프로토콜이 있다고 가정합니다. 가상의 read_message 동작은 먼저 헤더를 수신하고, 길이를 얻어 다음으로 바디를 수신하는 두번의 read를 사용해 구현될 것입니다.

 

비동기 모델에서 함수를 구성하기 위해 비동기 동작은 서로 연결 될 수 있습니다. 즉, 한 동작을 위한 Completion handler가 다음 동작을 초기화 할 수 있습니다. 연쇄 동작의 첫 호출을 캡슐화 함으로써 호출자는 상위 수준의 동작이 연쇄적인 비동기 동작임을 신경쓰지 않아도 됩니다.

 

이러한 방법으로 새로운 동작을 구성하는 것은 정의된 프로토콜을 지원하는 함수같은 네트워크 라이브러리의 상위 수준의 추상화 개발을 단순화 시켜줍니다.

 

단점

 

  • 프로그램 복잡도

 

비동기적 메커니즘을 사용한 프로그램의 개발은 동작의 초기화와 완료 사이의 시공간의 단절로 보다 어렵습니다. 프로그램의 디버깅 또한 역전된 제어 흐름으로 인해 더 어려울 것입니다.

 

  • 메모리 사용

 

버퍼 공간이 입출력 동작 동안 무기한으로 할당되어야 합니다. 또한 각각의 동시적 동작을 위해 분리된 버퍼가 필요합니다. 반면, Reactor 패턴의 경우는 소켓이 읽기 또는 쓰기가 준비될 때까지는 버퍼 공간이 필요하지 않습니다.

 

참고자료

 

[POSA2] D. Schmidt et al, Pattern Oriented Software Architecture, Volume 2. Wiley, 2000.