[원문출처] http://camel.apache.org/error-handling-in-camel.html


해당 문서의 경우 Apache 재단의 Camel Document 문서 일부를 번역 한 것입니다.
번역본인 해당 문서의 경우 역자에게 있음을 알리며 상업적 이용을 불허합니다. 

www.sogomsoft.co.kr (주) 소곰소프트 





Camel에서 에러 핸들링 (Error handling in Camel)

카멜에서 에러 핸들링을 하는 방법은 대략 두가지 유형으로 구분 된다. :

  • non transactional (트랜잭션이 적용되지 않는)
  • transactional(트랜잭션이 적용되는)

Camel에 의해서 활성화되고 통제되는 비 트랜잭션(트랜잭션이 적용되지 않는) 유형이 가장 일반적이다. 트랜잭션(트랜잭션이 적용되는)유형은 J2EE 어플리케이션 서버처럼 지원 시스템에 해 통제된다.

try ... catch ... finally 구문 사용하기

Camel에서 Try Catch Finally 기능이 에러 핸들링에 관련된다.

에러가 발생 했을 때 (When does an error happen)

에러가 발생 했을 때 

  • Camel내에서 메시지를 라우팅하고 처리 하는 동안 처리되지 않은 Exception이 발생한다.

    그래서 모든 예외를 잡아내고 무엇을 해야 하는지 통제하는 큰 Exception 인터셉터처럼 생각한다. 

비 트랜잭션 (Non transactional : 트랜잭션이 적용되지 않는)

기본적으로 Camel은 비트랜잭션 (트랜잭션이 적용되지 않은) 유형을 사용하고 처리하고 라우팅 하는 동안 에러를 핸들링하는 것 조율한다.

모든 경우에 적용할 단일 에러 핸들링 환경구성이 없기 때문에, 필요로 하는 더 적당한 기본 환경 구성을 바꾸는 것을 고려하여야 한다.

Came 1.x 기본 에러 핸들러 (Camel 1.x default error handler)

Camel 1.x에서 기본적으로 Error Handler 로 전역 Dead Letter Channel 이 설정된다. Dead Letter Channel 은 다음처럼 환경 구성되어있다.:

  • 6번까지 재 전송.
  • 각각의 재 전송 시도마다 1초의 일시 정지
  • 만약 모든 재 전송 시도가 실패하면 데드 레터 큐(dead letter queue)로 exchange를 옮긴다. 
  • 기본 데드 레터 큐(dead letter queue)가 ERROR level (star)에 exchange를 로깅하는 로거이다. 

Dead Letter Queue (*)

데드 레터 큐(dead letter queue)는 블랙홀 같다. Exchange를 소비하게 되고 실패했다는 어떠한 표시도 없이 Exchange 라우팅이 끝난다. 

시스템의 리소스를 다 사용해버리기 때문에 잘못된 메시지가 끝없이 재시도하는 것을 원하지 않는JMS 메시징에서 이 작업은 훌륭하다. 메시지들 독이 되는 것처럼 말하고 그러므로 우리는 메시지를 데드 레터 큐(dead letter queue)에 옮겨서 시스템이 계속 조작하고 다음 메시지를 작업 할 수 있다.

기본 값은 요청/응답(request/reply) 메시징 스타일에서 사용하는 다른 Transport로 잘 되지 않는다. 만약 Exchange 실패하면 원래 요청자는 실패 되었다는 것으로 변경 되기를 원한다. 

그래서 결론은 비즈니스적 요구에 적함한 에러 핸들링을 환경 구성하고 설정해야만 한다.  

Camel 2.o 이후 기본 에러 핸들러 (Camel 2.0 onwards default error handler)

Camel 2.0 이후부터는 기본적으로 Error Handler 로 전역 DefaultErrorHandler 설정된다. DefaultErrorHandler는 다음처럼 환경 구성되어 있다. :

  • 재 전송 없음
  • 데드 레터 큐(dead letter queue) 없음
  • 만약 exchage가 실패 하면 Exception을 던지고 RuntimeCamelException에 싸서 원래 요청자에게 다시 전파한다.

Scopes

Camel은 2 Scope를 지원하고 DSL에 의해 결정된다. :

DSL

Scope 1

Scope 2

Note

XML DSL

CamelContext

route

Scope 2가 Scope 1보다 우선한다.

Java/Scala DSL

RouteBuilder

route

Scope 2가 Scope 1보다 우선한다.

XML DSL을 사용할 때 scope 1은 모든 라우터를 위해 적용한다.  Java DSL을 사용할 때  route 1은 단지 주어진 RouterBuilder 인스턴스을 위해 적용된다. 그래서 만약 복수의 RouterBuilder들을 가지고 있을 때 각각의 라우터 빌더가 자신의 Scope 1가진다.

만약 RouterBuilder 들 사이에 Scope를 공유하기를 원하면 클래스 상속을 사용할 수 있다. 기본 클래스를 생성하고 RouterBuilder들을 위해 클래스를 확장하고 super.configure() 메서드를 호출한다.

복수의 RouteBuilder 클래스를 사용할 때 scope가 영향을 받은 것은 Camel 에서 버그가 였다는 것을 신경써라 다음 CAMEL-5456 에서 자세히 보라..

어떻게 데드 레터 채널(Dead Letter Channel) 에러 핸들러가  동작을 하는가?

Camel에서 시작될 때 라우터를 검사하게 되고 라우팅에 에러 핸들링을 짜넣는다. 최대 3까지 지원되는 Scope로, 에러 핸들링이 매우 복잡해 질 수 있다. 그리고 상단에서 에러 핸들을 상속 받고 다른 특정 Exception 유형을 핸들링하기 위한 Exception Clause들을 환경 구성할 수 있다. 그래서 에러의 핸들링 할 때 진보 되었으며 매우 파워풀하다.

단순하게 유지하기 위해 먼저 어떻게 Camel이 재 전송 횟수를 조율하는지 기본 개념을 찾아 보라. 라우터 그래프에서 주어진 노드에 Camel이 현재 라우팅 되고 있는 Exchange를 가로채어서 Error Handler로 감싼다. AOP around 개념처럼 Error Handlere가 차 넣을 수 있다. 만약 Exchange가 아무런 문제 없이 라우팅 될 수 있다면 라우터 그래프에서 다음 노드로 전달 된다. 그러나 만약 Exception이 발생하면 Error Handler라 차 넣고 어떻게 할지 결정한다..

이 설명의 예제 :

errorHandler(deadLetterChannel("jms:queue:dead"));
 
from("seda:newOrder")
   .to("bean:validateOrder")
   .to("bean:storeOrder")
   .to("bean:confirmOrder");

이 라우터는 Error Handler가 감시하고 있는 3개 노드를 가지고 있다 (AOP around 방식). 그래서 seda 큐에 요청이 도착했을 때 그것을 소비하고 validateOrder 빈에 보낸다. 이 경우에 validation 빈이 정상 처리 되면 , 다음 노드로 이동한다. 이 경우에 storeOrder 빈이 실패하고 Exception을 발생 시키면 Dead Letter Channel에 의해서 걸려서 다음에 무엇을 할 것인지 결정한다. 다음 중에 하나를 한다.:

  • 재전송
  • 데드 레터 큐(dead letter queue)로 이동

정책에 환경 구성에 근거 하여 재전송하기 위해 계속 할 것 이다. 기본적으로 Dead Letter Channel은 적어도 1초의 지연 시간을 두고 6회 재 시도를 할 것이다. 그래서 만약 3번째 시도 만에 storeOrder 빈이 성공하면 다음 노드인 confirmOrder 빈에 라우팅이 계속 될 것이다.  이 경우에 모든 재전송이 실패 하면 실패로 간주되고 데드 레터 큐(dead letter queue)로 이동되고 이 exchange의 처리는 멈춘다. 기본적으로 데드 레터 큐(dead letter queue)는 단지 ERROR 로거 이다.

Camel의 모든 컴포넌트에 적용된다. 위 예제는 단지 Bean을 사용했다 그러나 FileMailVelocity  또는 사용하는 모든 컴포넌트가 같다.

트랜잭션 (Transactional: 트랜잭션이 적용되는)

Camel은 Spring transactions을 활용한다. 보통 JMS 또는 JDBC 기반처럼 제한된 전송 유형의 수만 사용 할 수 있다.  Spring 트랜잭션, J2EE 서버나 Message Broker 같은 아직 필요하다. 

어떻게 동작하는가?

Camel 1.x
Camel은 비 트랜잭션 유형처럼 같이 짜넣는다. 다른 점은 트랜잭션 Exchange를 위해 Error Handler가 차 넣을 수 없다. AOP around가 적용되지 않는다고 말 할 수 있다. Camel은 에러를 핸들링을 조율하기 위해 지원 시스템에 전적으로 의존한다. 그리고 지원시스템이 재전송 할 때 모두 다시 시작하게 된다. 예를 들면 만약 Exchange가 JMS Comsumer에 의해 시작 되었다면 JMS 메시지가 JMS 큐에 롤백되어 다시 시작하게 되고 Camel 다시 JMS 메시지를 재 소비한다.

Camel 2.0
Camel 2.0에서 TransactionErrorHandler가 DefaultErrorHandler 가 했던 것처럼 같은 기반 위에 빌드 될때 권한을 부여 받았다. 이는 트랜잭션 라우터들로 Camel 재전송을 사용하는 것을 허용한다.  Spring transaction manager가 여전히 담당하고 있고 마지막에 동작한다. 그러나 몇몇 로컬 재전송을 하기 위해 Camel을 사용할 수 있다. 예를 들면 FTP 서버에 파일을 올리기 위해 Camel에서 로컬 재전송을 사용할 수 있다. 그래서 양쪽 모두에게 유용하다.    is still in charge and have the last say. But you can use Camel to do some local redelivery, for instance to upload a file to a FTP server, in which Camel can do local redelivery. So this gives you the power from both worlds. 경우에 Camel이 Exchange가 실패 되거나 롤백 되면 재전송 할 수 없다.기본적으로 TransactionErrorHandler 는 어떤 로컬 재전송도 시도하지 않는다 그래서 로컬 재전송을 하기서 예를 들면 최대 재전송에 0보다 큰 숫자를 설정하는 환경 구성을 해야 한다. 

더 자세한 것은 Transactional Client 보라.

참조 (See also)


+ Recent posts