[Akka] Classic Networking I/O

smlee·2023년 9월 12일
0

Akka

목록 보기
20/50
post-thumbnail

Akka의 I/O API는 액터 기반의 API이다. 즉, 모든 연산들은 직접적인 메서드 호출 대신 메시지를 패싱하는 방식으로 이루어진다. TCP나 UDP 같은 모든 I/O 드라이버들은 매니저라고 불리는 특별한 액터를 가지고 있다. 매니저라는 액터는 API의 entry point를 관리한다.

밑은 예시이다. 각각의 드라이버의 메니터는 IO entry point를 통해 접근 가능하다. 밑의 예시를 보며 TCP 매니저와 그 ActorRef를 리턴하는 코드를 알아보자.

import akka.io.{ IO, Tcp }
import context.system // implicitly used by IO(Tcp)

val manager = IO(Tcp)

매니저는 I/O 커맨드 메시지를 받고 워커 액터를 인스턴스화를 한다.

Requirements

방대한 범위의 애플리케이션을 위한 일반적이고 확장 가능한 I/O layer을 위해, 다음의 요구조건이 키 드라이버로 생성된다.

  1. 동시성 커넥션
    2.입력 채널에서 대상 행위자의 우편함으로 데이터를 가져오는 데 있어 가능한 최소화
  2. 최대 처리량
  3. 양방향 역압 옵션(즉, 로컬 송신기 조절뿐만 아니라 프로토콜에 의해 허용되는 경우 로컬 판독기가 원격 송신기를 조절할 수 있도록 허용)
  4. 불변의 데이터 표현을 가진 순수 배우 기반 API
  5. 목적은 I/O 메커니즘을 가장 낮은 공통 분모로 강요하지 않고 대신 완전히 프로토콜별 사용자 수준 API를 허용하는 것이다.

기초 아키텍처

각각의 전송 구현은 별개의 Akka 확장으로서 이용가능하게 될 것이고, 클라이언트 코드에 대한 초기 접촉점을 나타내는 ActorRef를 제공한다. 이 "관리자"는 통신 채널(예를 들어, TCP 소켓 상에서 연결 또는 청취)을 확립하기 위한 요청을 받아들인다. 각각의 통신 채널은 그 전체 생애에 걸쳐 이 채널과의 모든 상호작용에 대해 클라이언트 코드에 노출되는 하나의 전용 액터에 의해 표현된다.

구현의 중심 요소는 전송-특정 "선택기" 액터이다; TCP의 경우에 이것은 java.nio.channels.Selector를 랩핑할 것이다. 채널 액터들은 그들의 할당된 선택 액터에 대응하는 메시지를 전송함으로써 그들의 채널의 가독성 또는 쓰기 가능성에 대한 관심을 등록한다. 그러나 실제 채널 읽기 및 쓰기는 채널 액터들 자체에 의해 수행되며, 이는 선택 액터들을 시간 소모적인 작업들로부터 해방시키고 그에 따라 낮은 레이턴시를 보장한다. 선택 액터의 유일한 책임은 기본 선택기의 키 세트의 관리 및 일반적으로 차단할 수 있는 유일한 동작인 실제 선택 동작이다.

선택자들에 대한 채널들의 할당은 관리자 액터에 의해 수행되고 채널의 전체 수명 동안 변경되지 않는다. 이에 의해, 관리 액터는 일부 구현-특정 분배 로직에 기초하여 하나 이상의 선택자 액터들에 걸쳐 새로운 채널들을 "스트라이프"한다. 이 로직은 (부분적으로) 선택자 액터들에게 위임될 수 있고, 이는 예를 들어, 그들이 그들 자신이 용량에 있다고 간주할 때 새로운 채널의 할당을 거부하도록 선택할 수 있다.

관리자 액터는 선택자 액터들을 생성(따라서 감독)하고, 선택자 액터들은 다시 그들의 채널 액터들을 생성하고 감독한다. 따라서 하나의 단일 전송 구현의 액터 계층은 세 개의 별개의 액터 레벨들로 구성되며, 맨 위에는 관리 액터들이, 리프에는 채널 액터들이, 중간 레벨에는 선택 액터들이 있다.

출력에 대한 역압박은 사용자가 쓰기 메시지 내에서 O/S 커널에 쓰기를 대기하는 것에 대한 확인을 받을지 여부를 지정할 수 있게 함으로써 활성화된다. 입력에 대한 역압박은 채널 액터에게 읽기가 해당 재개 명령으로 다시 활성화될 때까지 채널에 대한 읽기 관심을 일시적으로 비활성화하는 메시지를 전송함으로써 활성화된다. TCP와 같이 흐름 제어 기능이 있는 전송의 경우, 수신단에서 데이터를 소비하지 않는 행위(따라서 커널 읽기 버퍼에 남아 있게 함)가 송신자에게 다시 전파되어 네트워크를 통해 이 두 메커니즘을 연결한다.

Design Benefits

전체 구현에 대해 액터 모델 내에 머무르는 것은 명시적 스레드 처리 로직의 필요성을 제거할 수 있으며, (기본 전송 라이브러리의 일부인 것들을 제외하고) 관련된 잠금이 없다는 것을 의미하기도 한다. 액터 코드만 작성하면 더 깔끔한 구현이 되는 반면, Akka의 효율적인 액터 메시징은 이러한 이점에 대해 높은 세금을 부과하지 않는다. 사실 I/O의 이벤트 기반 특성은 액터 모델에 매우 잘 매핑되므로 명확한 성능 및 특히 명시적 스레드 관리 및 동기화가 있는 전통적인 솔루션에 비해 확장성 이점을 기대할 수 있다.

감독 계층 구조의 또 다른 이점은 자원 정리가 자연스럽게 이루어진다는 것이다: 선택자 액터를 종료하면 모든 채널 액터가 자동으로 정리되어 채널을 적절하게 닫고 사용자 수준 클라이언트 액터에게 적절한 메시지를 보낼 수 있다. 데스워치는 채널 액터가 사용자 수준 핸들러 액터의 소멸을 눈치채고 그 경우에도 질서정연한 방식으로 종료되도록 한다. 이는 오픈 채널을 유출할 가능성을 자연스럽게 줄여준다.

모든 기능을 노출하기 위해 ActorRef를 사용하는 선택은 원격 및 라이프사이클 모니터링의 사용을 포함하여 일반적으로 사용자가 적합하다고 생각하는 대로 이러한 참조를 자유롭게 배포 또는 위임할 수 있다는 것을 수반한다(단, 두 번째 이름).

새 전송 추가 방법

가장 좋은 시작은 TCP 참조 구현을 연구하여 기본 작동 원리를 잘 파악한 다음 구현을 설계하는 것인데, 이것은 정신적으로 비슷하지만 문제의 새로운 프로토콜에 적응한 것이다. I/O 메커니즘 사이에는 방대한 차이가 있으며(예를 들어, 파일 I/O를 메시지 브로커와 비교), 이 I/O 계층의 목표는 모든 것을 균일한 API로 만들어내지 않는 것이며, 이것이 바로 기본 아키텍처 아이디어만 여기에 문서화하는 이유이다.

Reference

0개의 댓글