런타임 엔진 서버

본 장에서는 AnyLink 런타임 엔진 서버의 컴포넌트와 아키텍처에 대해서 설명한다.

1. 서버 컴포넌트

AnyLink 런타임 엔진 서버는 역할에 따라 프로토콜별 I/O 처리를 담당하는 어댑터와 제어의 흐름을 결정하는 서비스 플로우 엔진, 여러 개의 서비스를 하나로 묶어서 처리할 수 있는 멀티바인딩 라우터로 구성된다.

figure component architecture
AnyLink 컴포넌트 구성

1.1. 서비스 플로우 엔진

AnyLink 서비스 플로우 엔진(Service Flow Engine)은 이벤트에 의해 트리거되는 프로세스 실행 엔진이다. 서비스 플로우 엔진이 처리하는 이벤트는 어댑터 등의 다른 컴포넌트가 넘겨주는 메시지이다.

서비스 플로우는 비즈니스 프로세스를 모델링하는 데 사용되는 표준인 BPMN(Business Process Modeling Notation)을 차용한 다이어그램을 통해 프로세스의 흐름을 표현한다. BPMN은 OMG(Object Management Group)에서 정의하고 있는 비즈니스 프로세스를 표현하는 모델링과 표기법 표준으로 비동기적이며 동시성이 필요한 프로세스를 잘 표현할 수 있다.

서비스 플로우는 스튜디오를 통하여 액티비티와 이벤트로 구성된 다이어그램 형태로 정의하며, 프로세스 흐름 외에 변수, 표현식, 매핑, 핸들러, 사용자 액티비티 등의 기능을 추가로 제공한다.

서비스 플로우는 어댑터 등의 컴포넌트로부터 전달된 메시지에 의해 만들어지며, 다른 어댑터 혹은 서비스 플로우를 호출하거나 메시지를 주고 받을 수 있다. 또한 조건 분기, 선택적 실행, 동시 실행 등의 기능을 가지며, 흐름을 제어하기 위한 상태를 저장하는 변수 개념을 가진다.

AnyLink 서비스 플로우 엔진은 비동기적이고 동시성이 필요한 프로세스를 잘 실행할 수 있는 특별한 아키텍처를 가지고 있으며, 엔진에 할당된 스레드 풀을 통해 프로세스를 실행한다.

figure service flow engine triggering
AnyLink 서비스 플로우 엔진 트리거링

1.2. 어댑터

AnyLink 런타임 엔진 서버에서 어댑터(Adapter)는 AnyLink가 연계해야 하는 각 대상들과의 연계를 쉽게 해주는 역할을 한다. 연계 대상의 프로토콜에 맞추어 입출력 처리를 통한 연계를 하거나, 연계 대상 애플리케이션의 라이브러리를 사용한 연계 등을 실행한다.

figure protocol application adapters
프로토콜 어댑터

AnyLink 어댑터는 입출력의 방향에 따라 크게 인바운드 룰과 아웃바운드 룰 두 가지 룰을 정의할 수 있다.

  • 인바운드 룰은 외부 시스템으로부터 AnyLink로 요청을 전달해주고, 그 결과 응답을 외부 시스템으로 돌려주는 역할을 한다.

  • 아웃바운드 룰은 AnyLink에서 외부 시스템을 호출하고, 그 결과 응답을 받는 역할을 한다.

프로토콜에 따라 인바운드 룰의 요청 메시지와 아웃바운드 룰의 응답 메시지의 구분이 어려운 경우가 있다. 이를 효율적으로 처리하기 위해 AnyLink는 외부 시스템으로부터 들어오는 메시지 파싱 룰(parsing rule)을 통해서 인바운드 룰의 요청 메시지인지 혹은 아웃바운드 룰의 응답 메시지인지 여부를 판단할 수 있게 설계되었다.

1.3. 멀티바인딩 라우터

멀티바인딩 라우터(Multi-Binding Router)는 서비스 컴포넌트 내부적인 라우팅이 실행 시점에 동적으로 이루어질 수 있는 컴포넌트 간 라우팅 기능을 담당하는 컴포넌트이다.

AnyLink는 내부적으로 컴포넌트 간에 메시지를 주고받는 방식으로 다른 컴포넌트를 트리거링(triggering)한다. 기능의 이름과 특정한 형태의 요청 메시지 자료형과 응답 메시지 자료형, 오류 응답 메시지 자료형 등을 규격화하여 AnyLink에서는 서비스라고 한다.

AnyLink에서는 다음을 내부적으로 서비스로 사용한다.

  • Receive 메시지 이벤트

    서비스 플로우 정의의 Receive 메시지 이벤트는 어댑터로부터 메시지를 넘겨받는다.

  • 아웃바운드 룰

    어댑터의 아웃바운드 룰은 서비스 플로우로부터 메시지를 넘겨받는다.

  • 멀티바인딩 룰

    서로 다른 서비스를 묶어서 하나의 서비스처럼 그룹핑하기 위한 용도로 사용된다. 서로 다른 서비스 플로우의 메시지 이벤트, 어댑터의 서로 다른 아웃바운드 룰 또는 다른 멀티바인딩 룰 등을 그룹으로 묶어서 하나의 서비스처럼 표현할 수 있다. 멀티바인딩 룰은 여러 개의 서비스로 구성된 그룹을 조건에 따라 또는 규칙에 따라 특정 서비스로 분기하거나 여러 개의 서비스로 멀티캐스트하는 기능을 제공한다.

2. 서버 아키텍처

AnyLink 런타임 엔진 서버는 대외 시스템들과 통신을 담당하는 어댑터와 처리 로직을 담당하는 서비스 플로우 엔진, 큰 두 가지 서비스 컴포넌트와 다양한 서비스간 라우팅을 제공하는 멀티바인딩 라우터 서비스 컴포넌트로 구성되어 있으며, 컴포넌트들간의 통신과 룰 배포 등을 위한 딜리버리 채널(Delivery Channel), 리소스 관리자 등의 서비스가 정의되어 있다.

2.1. 시스템 아키텍처

본 절에서는 런타임 엔진 서버의 시스템 아키텍처에 대해서 설명한다.

 

런타임 엔진 서비스 컨테이너

런타임 엔진 서비스 컨테이너(RTE Service Container)는 컴포넌트의 라이프사이클을 관리하고 컴포넌트에 필요한 서비스들을 정의하고 제공하는 역할을 한다. 서비스 플로우 엔진, 멀티바인딩 라우터, 어댑터 관리자 등을 실행시켜주는 역할을 한다.

주요 서비스로 내부 통신 채널인 딜리버리 채널(Delivery Channel), 서비스 플로우 엔진과 어댑터 룰 등의 배포와 적재를 관리해주는 리소스 관리자, 스레드 풀과 로깅 등과 같은 시스템 자원을 관리하는 시스템 리소스 관리자, 각종 룰과 플로우에 사용되는 자바 코드들을 로드하기 위한 비즈니스 클래스 로더(Business ClassLoader) 등을 제공한다.

서비스 플로우 엔진 컴포넌트와 멀티바인딩 라우터 컴포넌트는 컨테이너별로 하나만 존재하며 어댑터 컴포넌트는 어댑터 종류별로 여러 개가 존재할 수 있다. 어댑터 컴포넌트는 어댑터 관리자가 기동 및 적재를 담당한다. 멀티바인딩 라우터 컴포넌트는 딜리버리 채널 내부에 존재하는 컴포넌트로 서비스를 라우팅할 때 서비스 ID 외에 다른 방식으로 라우팅을 하기 위한 컴포넌트이다.

figure rte container
런타임 엔진 서비스 컨테이너 구성

 

엔진 아키텍처

AnyLink 엔진은 효율적으로 대량의 입출력 채널을 관리하는 I/O 구조와 스레드 자원의 낭비를 최소화하는 비동기적 프로세싱 구조를 가지고 있다.

AnyLink 주요 통신 어댑터는 I/O 멀티플렉싱 방식의 입출력 처리를 하며, 특정 I/O 채널의 버퍼링에 다른 채널 처리가 영향받지 않도록 full non-blocking 방식의 처리를 구현하고 있다. 스레드 풀에서 주로 실행되는 서비스 플로우 엔진은 wait 시간을 최소화하도록 최대한 비동기적 특성을 가지도록 구현되어 있어서, 다수의 서비스 플로우가 동시에 실행되더라도 스레드 풀 부족으로 지체되지 않도록 고안되었다.

figure rte io thread arch
런타임 엔진 I/O 및 스레드 아키텍처

2.2. 딜리버리 채널

딜리버리 채널(Delivery Channel)은 미리 정의된 유형의 메시지 패턴을 통해 서비스 컴포넌트들간의 내부 통신을 비동기적인 방식으로 지원하는 서비스이다. 서비스 컴포넌트들 간의 의존성을 줄여주는 핵심 아키텍처이며, 메시징 API에 따라 적절한 스레드 풀을 사용하는 등의 기능을 가지고 있다.

figure delivery channel system arch
Delivery Channel 시스템 아키텍처
  • 메시지 패턴

    딜리버리 채널은 서비스 컴포넌트들 간 내부 통신을 몇 가지 패턴 형태로 제공한다.

    구분 설명

    Request-Response(2way)

    가장 일반적인 메시징 형태로 요청에 대한 응답을 기대하는 형태이다.

    Oneway

    응답을 기다리지 않고 요청 메시지만 전달하는 형태이다.

    Oneway-ACK

    요청 메시지가 처리된 후에 ACK 메시지를 기대하는 형태이다. 보통 딜리버리 채널에서 전달 보장을 처리한 후 ACK 메시지 혹은 NAK 메시지를 답변으로 보낸다.

    Request-Response-ACK(3way)

    요청, 응답 메시지 외에 응답에 대한 ACK 메시지가 추가된 형태이다. 응답 메시지를 잘 처리하였는지를 알려주는 ACK 혹은 NAK 메시지를 전달해줘야 한다.

    Test-Message

    요청 메시지를 처리할 수 있는지 여부를 질의하는 메시지 형태이다. 멀티바인딩 라우터에서 코릴레이션 매칭(Correlation Matching) 방식의 라우팅을 위해 사용한다. 코릴레이션 매칭에 대해서는 코릴레이션을 참고한다.

    figure request response ack
    Request-Response-ACK 컴포넌트 통신
  • 신뢰 전송(Reliable Messaging) 및 XA 전송

    딜리버리 채널은 OneWay 메시지 패턴을 사용할 경우 선택적으로 신뢰 전송과 XA 전송을 지원한다.

    구분 설명

    신뢰 전송

    영구 저장 장치인 디스크나 RDBMS에 메시지를 저장한 후 ACK을 주는 방식으로 구현되어 있다.

    XA 전송

    Global Transaction을 지원하기 위해 지원하는데, 주로 Tmax 어댑터에서 Global Transaction이 걸려있는 상태에서 여러 개의 메시지가 전달될 경우에 사용한다. Tmax 어댑터를 통해 prepare, commit, rollbACK 등의 글로벌 트랜잭션 2-phase commit 관련 메시지를 처리하여 하나의 트랜잭션으로 묶여있는 여러 건의 메시지를 일괄 처리할 수 있도록 지원한다.

  • 트랜잭션 전파(Transaction Propagation)

    딜리버리 채널은 메시지 속성에 따라 트랜잭션을 시작 혹은 종료하거나 트랜잭션 문맥을 전파하는 역할을 한다. 또한 스스로를 글로벌 트랜잭션의 XA 리소스 관리자 역할을 할 수 있다.

    딜리버리 채널은 Tmax나 JEUS 등 트랜잭션 매니저(Transaction Manager)로부터 들어오는 메시지의 트랜잭션 문맥을 받아서 트랜잭션에 참여할 수 있는 기능을 제공하며, 그 반대로 스스로를 트랜잭션 매니저로 동작하여 AnyLink 내부적으로 트랜잭션을 시작하고 또 외부의 RDBMS와 같은 XA 리소스 관리자나 JEUS, Tmax 등으로 글로벌 트랜잭션을 전파할 수 있는 기능을 제공한다. 개별 트랜잭션의 설정은 서비스 플로우나 각 어댑터 룰의 속성으로 설정을 한다.

2.3. 런타임 엔진 서비스

런타임 엔진 서비스 컨테이너는 딜리버리 채널 외에도 런타임 운영에 필요한 서비스들 제공한다.

  • 리소스 관리자

    내부적으로 정의하는 업무의 거래 및 거래그룹에 속하는 각종 룰과 리소스, Java 코드들을 관리한다.

  • 시스템 리소스 관리자

    런타임 엔진이 사용하는 스레드 풀과 시스템 로깅을 관리한다.

  • 비즈니스 클래스 로더

    Java 코드 및 주요 리소스들의 계층 구조 및 Symbolic Link 등 의존성 처리를 구현한 Java 코드 클래스로더이다.

  • 배포 관리자

    데이터 통합 서버(DIS)로부터 여러 가지 리소스를 안정적으로 배포하기 위해 2-phase 배포를 구현하는 서비스이다. 데이터 통합 서버로부터 배포할 리소스를 넘겨받아 동적으로 배포를 실행하며, Undeploy(배포 해지)나 Redeploy(재배포)가 발생하면 기존의 리소스 파일은 백업 디렉터리로 이동시키고 삭제 혹은 갱신을 하게 된다. 런타임 엔진의 배포 서비스가 배포의 1단계(prepare)에서 오류를 발생시키면 DIS는 전체 서버로의 배포를 취소(rollback)시킨다.

3. 런타임 엔진 에러 처리

AnyLink는 여러 경우의 오류를 다루는 방법을 제시하고 있다. 어느 수준에서 발생하는 오류인가에 따라 용어도 다르고 처리하는 방식도 다르다. 본 절에서는 런타임 엔진에서 발생하는 예러의 처리방법에 대해서 간단히 설명한다.

3.1. 딜리버리 채널

AnyLink 런타임 엔진 내부의 서비스 컴포넌트 간 통신 채널인 딜리버리 채널에서 하나의 서비스 컴포넌트로 다른 서비스 컴포넌트로 메시지를 전달할 때 발생하는 에러 처리가 있다. 이 부분은 시스템 내부적인 오류이므로 AnyLink 사용자가 고려할 필요는 없지만, 내부적인 동작 방식을 이해하는 데 도움이 될 수 있다.

엔진 내부의 서비스 컴포넌트들 간의 통신을 담당하는 딜리버리 채널은 응답과 에러 응답을 구분하여 보내도록 구성되어 있다. 딜리버리 채널의 에러 응답은 서비스 컴포넌트에서 메시지를 처리하다가 내부적으로 오류가 발생하였을 때 이 에러를 응답으로 보내기 위한 것이다.

딜리버리 채널의 에러 응답은 업무적 관점의 비정상 응답과는 다르다. 업무적 관점의 비정상 응답은 딜리버리 채널에서는 정상 응답과 마찬가지로 응답 메시지를 통해 전달되어야 한다. 즉, 각 서비스 컴포넌트들은 비정상 응답 메시지를 보낼 때에는 딜리버리 채널에서 정상 응답 메시지를 보내는 방식과 동일한 API를 사용하고, 에러를 보낼 때에는 에러를 전달하는 별도의 API를 사용한다.

3.2. 서비스 플로우

AnyLink 서비스 플로우 정의는 내부적으로 에러 이벤트와 에러 핸들러, 에러 코드 매퍼를 정의하고 있다 또, 서비스 요청에 대한 비정상 응답을 처리하는 메커니즘도 정의하고 있다.

  • 에러 이벤트

    AnyLink 서비스 플로우는 흐름 제어를 위해 에러 이벤트를 발생시키거나(끝 이벤트로 에러 이벤트를 사용할 경우), 감지할(바운더리 이벤트로 에러 이벤트를 사용할 경우) 수 있다.

    에러 이벤트를 던지거나 받을 때에는 에러 코드를 사용한다. 서비스 플로우 인스턴스를 실행하는 도중 내부에서 예기치 않은 오류가 발생할 경우(Java 언어의 Exception이 발생한 경우)에는 이를 에러 코드로 변환하는 에러 코드 매퍼를 사용할 수가 있다. 즉, 에러 코드 매퍼는 Java 언어의 Exception이 발생했을 때, 이것을 서비스 플로우가 알 수 있는 에러 코드로 변환해 주는 인터페이스이다.

    기본적으로는 에러 코드 매퍼가 정의되어 있지 않는데, 에러 코드로 변환되지 않은 Exception은 해당 Exception 객체의 전체 클래스 이름이 에러 코드로 사용된다. 바운더리 이벤트로 에러를 잡을 때 에러 코드를 지정할 수 있는데, ALL을 선택하면 Exception 종류나 에러 코드 값에 관계없이 모든 에러를 잡을 수 있다.

  • 에러 핸들러

    서비스 플로우별로 지정할 수 있는 프로세스 에러 핸들러와 액티비티별로 지정할 수 있는 액티비티 에러 핸들러가 있다. 서비스 플로우 인스턴스 실행 도중 Exception이 발생했을 때 액티비티 혹은 프로세스 에러 핸들러가 지정되어 있으면 이 에러를 처리하여 서비스 플로우를 정상적으로 진행시킬 수 있다.

  • 서비스 액티비티의 비정상 응답

    어댑터 아웃바운드 룰이나 멀티바인딩 라우터 룰과 같은 서비스를 호출하였을 때 비정상 응답을 받을 수 있다. 비정상 응답의 정의는 비정상 응답을 보내는 쪽에서 문맥적으로 정의된다. 비정상 응답이 발생할 수 있는 경우에는 비정상 응답을 위한 매핑을 별도로 지정할 수 있다.

    서비스가 비정상 응답을 보내 올 경우에 액티비티에서 비정상 응답 매핑이나 비정상 응답 파라미터를 지정하지 않으면, 응답 매핑이나 응답 파라미터을 대신 사용하는 것이 아니라 비정상 응답 전문을 파라미터에 저장하지 않게 되므로 주의해야 한다.

    AnyLink 서비스 플로우에서 비정상 응답은 에러 이벤트와는 상관이 없다. 즉, 비정상 응답은 서비스 플로우의 에러를 처리하는 흐름 제어 방식과는 관련이 없다.

3.3. 어댑터

어댑터는 파싱 룰에서 응답 메시지 외에 비정상 응답 메시지를 정의하고 있으며, 어댑터의 엔드포인트에서 내부 시스템 에러가 발생했을 때 시스템 에러 메시지를 정의할 수 있도록 하고 있다.

어댑터는 파싱 룰과 아웃바운드 룰에서 각각 요청 메시지와 응답 메시지, 비정상 응답 메시지를 정의하게 되어 있다. 또 시스템 에러, 포맷 에러 등 다양한 에러 시나리오에 대한 대응을 지정할 수 있도록 룰이 설계되어 있다. 어댑터의 에러 처리에 대한 상세 내용은 해당 어댑터 안내서를 참고할 수 있다.