메시지 큐를 이용한 비동기 요청 처리
-
요청을 처리하는 방법에는 전통적인 동기식 방식도 있지만, 비동기식 방식도 있는데, 동기 방식이 클라이언트가 요청을 보내면 처리한 다음에 응답이 오는 방식이라면 비동기 방식은 요청을 보낸 후 비즈니스 로직이 처리가 완료되지 않은 상태에서 다음 로직을 진행한다.
-
서버로 전달된 요청은 나중에 처리되며 나중에 클라이언트로 응답이 전달된다. (응답을 전달하지 않을 때도 있다.)
-
동기식 방식과 비동기식 방식의 가장 큰 차이점은 동기식 방식은 응답이 올 때까지 클라이언트가 대기하는 것이고, 비동기식 방식은 요청만 보내놓고 응답이 오는 것과 상관없이 클라이언트 대기 없이 다음 로직을 수행한다.
-
선택적으로 콜백 메시지를 보내는 경우가 있는데, 콜백은 클라이언트에게 비동기로 요청된 작업이 끝났음을 알려주는 호출이다.
-
예를 들어서, 페이스북 사진을 첨부해서 글을 올리면, 브라우저에서는 글이 등록되었다고는 하지만 바로 타임라인에 표시되지 않고 1 ~ 2 초 후에 업데이트 되는 것을 확인할 수 있다.
-
이는 브라우저에서 글쓰기 요청을 받으면 먼저 클라이언트에게 완료되었다는 응답을 보낸 후 서버는 뒷단에서 그림의 크기를 조정하는 등의 추가적인 작업을 한후에 데이터베이스에 저장한 후 타임라인에 반영하기 때문이다. 이러한 처리가 대표적인 비동기 처리의 예이다.
-
주로 시간이 오래 걸리는 대규모 작업에 유리하고, 동영상 인코딩 같은 변환 작업이나 시간이 오래 걸리는 계산 작업, 또는 하나의 메시지를 보냈지만 여러 개의 작업이 필요한 경우 등 여러 시나리오에 폭 넓게 사용할 수 있다.
-
이러한 비동기식 패턴 구현에는 일반적으로 메시지 큐라는 것을 사용한다.
-
이 메시지 큐는 들어온 요청을 쌓아놓는 임시 공간으로, 쌓여있는 요청 메시지는 뒤의 비즈니스에 의해서 처리 된다.
에러 처리
-
이러한 비동기식 구현에서 가장 중요하게 고려해야 할 사항은 전달된 요청 메시지가 잘 처리되었느냐이다.
-
클라이언트는 단순하게 요청을 보내고, 그에 대한 응답을 받지 않기 때문에, 해당 요청이 제대로 처리되었는지 보장할 방법이 없다.
-
예를 들어서 클라이언트는 요청을 보내고 메시지 큐에 잘 저장된 후에 응답을 받는다. 이 상태에서 클라이언트는 이 메시지가 제대로 처리될 것을 기대하지만, 메시지 큐에서 해당 메시지를 읽어서 처리하는 서버가 메시지를 꺼내서 처리하다가 장애를 일으켜서 정지하였다고 가정해보면 그 메시지는 유실되고 처리되지 않게 된다.
-
따라서 이러한 비동기 구현에서는 에러 처리 부분에 가장 많은 신경을 써야 한다.
-
비즈니스 컴포넌트에서 메시지 처리 중 에러가 났을 때, 해당 메시지를 에러 큐라는 재처리용 큐로 전달한다. 메시지의 에러 처리 정책을 정해서 에러를 어떻게 처리할지를 지정할 수 있는데, 비동기 메시지 처리에서는 다음과 같이 크게 4가지 정책을 사용하고 있다.
1. 재처리 (Retry)
- 메시지 처리 중 에러가 발생하였을 때, 다시 처리를 시도하도록 하는 방법ㅇ다.
- 메시지를 처리하는 비즈니스 컴포넌트가 일시적인 장애 (네트워크 문제, 리소스 부족 등) 일 경우에는 효율적으로 사용할 수 있다.
- 재처리를 할 때는 반드시 최대 재처리 횟수를 지정해야 한다. (통상적으로 3 ~ 5 번 정도를 사용한다).
- 그리고 재처리를 할 때, 에러 발생 후 바로 재처리를 시도하면 같은 원인으로 같은 에러가 발생할 수 있기 때문에 일정 시간을 기다렸다가 다시 처리하는 것이 좋다.
2. 무시 (Ignore)
- 에러가 난 메시지는 무시하고 메시지를 없애 버리는 방식이다. 중요하지 않는 로그 정보를 저장할 때와 같이 메시지 유실이 허용되는 경우에만 사용한다.
3. 알림 (Notify)
- 메시지 처리 중 에러가 발생하였을 때 이메일,
SMS
등을 이용하여 관리자에게 통보하여 관리자가 직접 에러에 대한 후 처리를 할 수 있도록 하는 방식이다.
4. 사람이 처리하도록 함 (Human Interaction)
- 에러가 발생하였을 때, 자동으로 처리하지 않고 관리자가 직접 처리할 수 있는 사용자 인터페이스를 제공한다.
- 관리자가 에러난 메시지를 확인하고 재처리할지 무시할지 등을 결정하도록 한다.
- 에러 재처리 부분이 복잡하거나 규모가 큰 경우 이런 메시지에 대한 에러 처리를 별도의 컴포넌트로 구현하기도 하는데, 이를
Error Hospital
이라고 부른다. 처리 중 에러가 난 메시지를 모아서 다양한 에러 처리 정책에 따라서 재처리를 할 수 있는 기능을 갖는다.
메시지 큐 구성 시 고려해야 할 사항
성능 및 페일 오버를 고려한 Persistence의 선택
-
메시지를 물리적으로 어디에 저장할 것인지 고민하는 것으로, 메시지는 보통 메모리, 디스크 또는
RDBMS
와 같은 저장소에 저장할 수 있다. -
보통 메모리에 저장하는 모델이 가장 빠르기는 하지만, 서버 장애가 났을 때는 처리되지 않은 메시지들이 유실 될 수 있는 위험이 있기 때문에 아주 고성능에 메시지 유실이 허용되는 시스템이 아닌 경우에는 사용하지 않는 것이 좋다.
-
여러 개의 메시지 큐를 클러스터링 해서 사용할 경우에는, 클러스터된 인스턴스 중 특정 인스턴스가 죽었을 경우, 처리되지 않은 메시지를 살아 있는 인스턴스로 넘기기 위해서는 이 파일 시스템이 인스턴스 간에 공유 되어야하는 경우가 있다.
-
이러 인해서
NFS(Network File System)
와 같은 공유 파일 저장소를 사용해야 하는 경우가 있는데, 이 경우NFS
성능 저하로 말미아마 전체 메시징 시스템의 성능 저하가 올 수 있기 때문에 이 부분에 대해서 고려해야 한다. -
가장 마지막 방법으로는
RDBMS
를 메시지 저장소로 사용할 수 있는데, 클러스터링 구성 시 페일 오버(Fail Over)도 비교적 잘되고, 메시지에 대한 관리도 매우 쉽다는 장점을 가지고 있지만, 3가지 구조 중에서 가장 느리고 추가적으로RDBMS
운영이 필요하다는 단점이 있다.
펜딩 메시지로 말미암은 Out of Memory
-
다음 고려사항으로, 메세지 큐 미들웨어는 메모리 과다 사용으로 말미 암은
Out of Memory
에러에 주의해야 한다. -
메모리에 메시지를 저장하는
Persistence
구조를 가지고 있을 경우에는 메시지를 큐에서 꺼내 가지 않은면 쌓여 있는 메시지들이 정체되어 메모리를 잡아먹으면서Out of Memory(메모리 부족 에러)
를 일으킨다. -
이렇게 쌓여있는 메세지들을 펜딩 (Pending Message) 라고 하는데, 이 펜딩 메시지에 의한
Out of Memory
에러는 메시지 저장소를 이용하지 않더라도 발생하는 경우가 있다. -
이는 메시지 큐 미들웨어의 특성상 성능 향상을 위해서 메시지를 파일이나
RDBMS
에 저장하더라도, 최소한의 메시지에 대한 메타 정보(메시지 ID와 같은 인덱스 정보)를 메모리에 저장할 때 발생할 수 있다.
트랜잭션 지원 기능
-
높은 신뢰성을 요구하는 시스템은 트랜잭션 지원 기능을 고려해야 하는데, 메시지를 큐에서 빼간 후에 처리하다가 에러가 났을 경우의 이 메시지는 다시 큐에 복귀되거나 또는 에러 큐로 보내져야 한다. 이런 기능을 지원 하려면 트랜잭션 지원 기능이 필요하다.
-
트랜잭션 기능을 지원하는 경우가 많지만 근래의
AMQP
나 고속 메시징 시스템의 경우 이러한 트랜잭션 기능을 지원하지 않는 경우가 많다. -
예를 들어서 큐에서 메시지를 읽고 그 메시지를 데이터베이스에 쓰는 것은 하나의 트랜잭션으로 묶는 경우, 메시지를 큐에서 꺼내 온 후 메시지를 데이터베이스에 넣는 것을 실패하였을 때 이 트랜잭션을 실패로 처리하고 메시지를 다시 큐에 돌려 넣거나 아니면 에러 큐에 보내야 하는데, 분산 트랜잭션을 지원하는 메시지 큐 시스템은 데이터베이스와 큐의 트랜잭션을 하나로 묶어서 자동으로 이러한 작업을 처리한다.
-
하지만 트랜잭션을 지원하지 않을 때에는 에러가 발생하였을 때, 개발자가 에러 큐로 메시지를 던지거나 또는 다시 큐에 넣는 작업을 해줘야 한다.
클러스터링 기능
-
마지막으로 클러스터링 지원 여부로, 메시지 큐에서 클러스터링이란 여러 개의 메시지 큐를 하나의 클러스터로 묶는 기능을 정의하느데, 여기서 오는 장점은 크게 두 가지 관점에서 고민 해 볼 수 있다.
-
첫 번째로는 클러스터링을 통해서 특정 인스턴스 장애 시 다른 인스턴스들이 장애가 난 인스턴스의 메시지를 받아서 처리하는 페일 오버(
Fail Over
) 기능이 있을 수 있다. -
두 번째로는 한 대의 서버로 처리할 수 없는 양의 메시지를 여러 대의 서버에서 분산 처리하면서 올 수 있는 장점이 있다.
-
메시지 큐 미들웨어는 한 번 선택이 되면 표준처럼 계속 사용되기 때문에 서비스의 특성을 잘 파악하고 위의 고려 사항을 기반으로 적절한 제품군을 선택할 것을 권고한다.