블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 

'Apache Camel'에 해당되는 글 3

  1. 2013.02.20 Apache Camel Error Handling
  2. 2013.02.17 Apache Camel Overview
  3. 2013.02.12 Apache Camel note
 

Apache Camel Error Handling

아키텍쳐 /EAI | 2013.02.20 00:54 | Posted by 조대협


Camel의 에러처리

먼저 Camel의 에러 타입에 대해서 살펴보자. 이 에러 타입은 Camel 이 아니더라도, 일반적인 integration 시나리오에서는 공통적으로 존재하는 에러 타입으로, 복구 가능한 에러와 복구 불가능한 에러가 있다.

에러의 종류

복구 가능한 에러 (Recoverable error)

복구 가능한 에러는 다시 시도 했을 경우 정상 처리 할 수 있는 에러이다. 예를 들어 순간적으로 네트워크 Connection이 끊어졌을때는 대부분, 다시 시도 하면 재처리가 가능하다.

복구 불가능한 에러 (Irrecoverable error)

복구 불가능한 에러는 내부 로직 문제나 잘못된 데이타 입력으로 인하여 다시 시도했을때에도 에러가 예상되는 에러를 복구 불가능 에러로 분리한다.

Camel에서 수신 컴포넌트에서부터 전달되는 메세지는 org.apache.camel.Exchange라는 클래스를 이용해서 전달이 되는데, 에러가 발생하면, 이 클래스에 에러를 Binding 시킬 수 있다. 에러 처리는 Camel Route 흐름에 따라서 Channel이라는 단계에서 처리된다. (Channel의 개념은 뒤에서 설명)

Recoverable 에러의 경우에는 Throwable이나 Exception 으로 정의하고, Exchange.setException() 메서드를 통해서 바인딩 한다.

Irrecoverable 에러의 경우에는

Message msg = Exchange.getOut();

msg.setFault(true)

로 설정해주면, 이 에러는 irrecoverable 에러로 정의된다이렇게 발생된 에러는 어떻게 처리 될까? 에러 처리 정책을 결정하는 ErrorHandler에 정의된 정책에 따라서 처리 된다.

ErrorHandler

어떻게 Error 가 처리 되는지를 설명하기 위해서 앞서 설명했던 Camel Route 흐름을 조금 더 자세하게 살펴보자




Camel은 앞서도 설명하였지만, 메세지를 수신 받는 Component, 이를 처리하는 Processor 그리고, 수신 시스템으로 송신하는 Component로 구성이 된다. 이 세 요소 사이에 메세지가 흘러가는데, 이 각각의 구간을 Channel이라고 정의한다. Channel은 단순히 논리적인 구간만이 아니라, 메세지가 흘러가는 길목으로 이 부분을 통해서 에러 처리나 모니터링 등의 (injection과 같은) 작업을 수행할 수 있다. 즉 에러 처리가 여기서 발생한다

에러가 발생하면, 에러는 전단계의 Channel로 넘어가게 되고, 정의된 ErrorHandler의 정책에 따라서 에러가 처리 된다. 즉 위의 그림에서 Processor에서 에러가 발생하면, Exception[1] Channel 부분으로 넘어가게 되고, 정의된 ErrorHandler에 의해서 처리된다. 마찬가지로 (Outbound) Component에서 에러가 발생하면 [2] Channel로 넘어가서 여기서 에러가 처리된다.

그러면 실제로 에러를 처리 하는 ErrorHandler를 살펴보자. Camel은 크게 5개의 Error Handler를 가지고 있다.


(1) DefaultErrorHandler

가장 일반적으로 사용되는 ErrorHandler이다. DefaultErrorHandler의 경우 에러가 발생하면, 앞단계로 Error Propagation한다.

, Processor에서 에러가 발생하면 앞단계의 Inbound Component Error propagte하고 Route process를 끝낸다. Inbound Component의 경우 내부적으로 자체 Error 처리 로직을 가지고 있는 경우가 있다. (File,FTP,DB Component의 경우) 이 컴포넌트들은 에러를 받으면 에러 처리를 한 후에 Route를 종료 시킨다.

만약 특정 에러가 발생하였을 때, Route를 정지 시키지 않고 진행을 하고 싶다면, Error 처리를 한 후에 뒤로 진행하도록 할 수 있다.

다음 코드를 보자

from(“src:start)
 .process(new MyProcessor())
 .to(“des:end”);

 

onException(StepBackException.class).log(“error sent back to caller”);

onException(HandledErrorException.class).handled(true).setBody(constant(“error handled”)).to(“des:errorhandle)

onException(IgnoreErrorException.class).continue(true);

 

이 코드는 별도의 ErrorHandler를 지정하지 않았기 때문에, Default Handler로 작동하고,

StepBackException 이 발생하면 앞단계로 Error propagate하고 Route를 종료한다.

HandledErrorException이 발생하면 handled(true)를 세팅하였기 때문에, setBody~ 부터의 흐름을 진행하여, des:errorhandle로 메세지를 전달한다.

IgnoreErrorException 이 발생하면, continue(true)에 의해서 에러를 무시하고 to(des:end)를 그대로 진행한다.

 

(2) DeadLetterChannel

Error가 발생되었을때, DeadLetterChannel로 메세지를 전송한다. 일반적으로 Message Queue 메카니즘을 사용할때 쓰는 일종의 ErrorQueue로 생각하면 된다.

RouterBuilder Class에서

public void configure(){

 errorHandler(deadLetterChannel("jms:queue:error_queue"));

 from(…)…

 to(…)..

}

와 같이 정의 해놓으면, 에러가 발생하였을때, 메세지를 JMS error_queue로 전송한다.

 

(3) LogErrorHandler

에러가 발생하였을 때, 설정된 Log4J등의 Logger를 통해서 에러를 출력한다.

그 외에 TransactionErrorHandler NoErrorHandler 등이 있다.

ErrorHandler들은 CamelContext에 적용하여 Context binding된 전체 Route들에 적용할 수도 있고, 또는 개개별 Route에만 적용할 수 도 있다.

에러의 재처리

DefaultErrorHandler의 경우, 에러가 발생하였을때, 재처리를 하도록 설정할 수 있다.

errorHandler(defaultErrorHandler().maximumRedeliveries(5))

로 지정하면 5 Retry를 하게 된다. 물론, retry 간격등이나, retry logging 등 다양한 옵션을 지정할 수 있다.

http://camel.apache.org/redeliverypolicy.html


참고 : Apache Camel 소개 -http://bcho.tistory.com/715


'아키텍쳐  > EAI' 카테고리의 다른 글

Apache Camel Error Handling  (0) 2013.02.20
Apache Camel Overview  (0) 2013.02.17
EAI (Enterprise Application Integration) 추진 전략  (2) 2009.07.16
ETL vs EAI  (0) 2009.06.16
EAI 도입 전략  (0) 2007.08.21

Apache Camel Overview

아키텍쳐 /EAI | 2013.02.17 00:43 | Posted by 조대협

조대협 (http://bcho.tistory.com)

서문

예전 BEA나 오라클 시절에, EAI, ESB 등을 가지고 시스템간의 연계 업무를 많이 해왔던 나로써는 오픈 소스 기반의 EAI 프레임웍인 Apache Camel의 경우 상당히 흥미로운 주제였다. 과연 상용 제품 대비 얼마나 현실성있는 integration 기능을 제공할 것인가? 가 가장 큰 궁금증이었다.

BEA WebLogic EAI, Oracle Service Bus, AIA 등 여러 제품을 이용해서 직접 시스템간의 연계 시나리오도 구현해보고, BMT에서 타의 솔루션을 테스트도 해봤지만, 먼저 상용 솔루션의 약점은, 솔루션에서 제공하는 시스템간의 연계에 있어서 성능적인 제약이 매우 많이 따른 다는 것이다. 대부분 Message Queue 구조의 비동기 구조를 통해서, 양단간에 데이타 연계를 하는 시나리오가 많은데, 이 경우 비주얼하게 각 단계에 대해서 모니터링은 가능 하지만, 대규모 처리에 있어서 비동기의 약점 때문에 성능적인 제약이 따르고 특히 대규모 메세지 처리에 있어서 그리 매끄럽지 못했던 경험이 있다. BPEL과 같은 제품의 경우 양단간의 연동 시나리오중, 개개별 메세지를 콘솔을 통해서 트레이스할 수 있는데, 하루에 수백,수천건을 연계하는 거래의 경우에는 GUI 콘솔을 통해서 메세지를 전달 내용이나 에러 내용을 추적한다는 것은 애초 부터 불가능한 일이다.

 그래서 실제 프로젝트 때에는 송수신 시스템을 연동하는 양쪽의 아답터 (JMS, 메인프레임, TP 모니터, ERP, CRM 등 다양한 시스템과 연동이 필요하기 때문에, 상용 제품에서 지원되는 아답터는 매우 중요하다)와 기본적인 메세지 플로우 이외의 부분은 대부분 직접 구현하였다. 그래서, EAI와 같은 제품에서 필요한 구조와 이런 것을 요구 사항에 맞게 빠르게 만들었으면 하는 프레임웍이 있었으면 했는데, Apache Camel을 보니, EAI와 같은 연계 업무성 프레임웍으로 적합해 보인다.

Apache Camel의 특징을 보면

Message Integration Framework

Camel은 기본적으로 Message Integration Framework이다. Framework임을 강조하는 것은, ESB EAI 제품과 같은 솔루션이라기 보다는 이를 개발하기 위한 Framework으로 보는 것이 적절하다고 판단된다.

이유는 ESB EAI는 메세지 연동 기능을 수행하기 위한 컨테이너가 있다. (즉 서버가 있다) 아무런 연동 인터페이스가 없더라도, 연동 인터페이스를 수용할 수 있는 컨테이너가 있고, 이 컨테이너들은 모니터링, 로깅등의 관리 기능을 제공한다. 그러나 CamelLibrary이다. 자체적으로 Container를 가지고 있지 않다. 다만, OSGI 컨테이너나 WAS, Spring등에 탑재 되서 돌아갈 수 있다. 쉽게 이야기 하면, EAI ESB와 같은 솔루션 제품은 서버를 설치해야 하고, 서버 관리를 위한 관리 콘솔 UI를 제공한다. Camel Jar로 된 라이브러리 이다.

상용 제품 연계에는 적절하지 않다.

Camel을 보면, 타 솔루션을 연동하기 위한 아답터, (Camel에서는 Component라고 부른다)가 있다. 50여개의 아답터가 있기는 하지만, 기업에서 많이 사용되는 솔루션의 아답터는 턱없이 부족하다. 예를 들어 SAP ERP, Sieble CRM, Tuxedo, AS/400 과 같은 애플리케이션에 대한 아답터 지원이 없다. 상용 제품의 경우 이런 아답터 지원이 강력하다.

반면, DB,FTP,HTTP,JMS와 같이 일반적인 애플리케이션 개발에 사용되는 기술에 대한 아답터는 많이 제공된다.

Apache Camel의 컨셉

Apache Camel의 컨셉을 대략적으로 도식화 해보면 다음과 같다.


Route

먼저 Route 라는 개념을 이해해야 하는데, Route하나의 시스템간의 연동 인터페이스를 정의한다. 예를 들어 시스템 A에서 B로 웹서비스를 이용해서 연동을 했다면 이것이 하나의 Route가 된다. Route 1:1 관계뿐만 아니라 1:N의 관계도 지원 하는데, A 시스템에서 B 시스템으로 JMS로 메세지를 보내고, 그후에 C 시스템으로 FTP 파일 전송하는 인터페이스가 있다면, 이 역시 하나의 Route로 정의할 수 있다.

Component

Route는 크게 Component Processor로 정의 된다. 연계 하고자 하는 송신 시스템과 수신 시스템이 있을때, 각 송신,수신 시스템의 주소(IP) end point라고 정의하며, Component는 일종의 아답터의 개념으로, 송수신 시스템의 프로토콜에 맞는 컴포넌트를 선택해야 한다. 예를 들어 송신 시스템을 FTP로 연동하고 싶다면, FTP 컴포넌트를 , JDBC로 연동하고 싶다면, JDBC 컴포넌트를 사용해야 한다. 컴포넌트는 송신 시스템으로 부터 메세지를 읽어드리고, 수신 시스템으로 메세지를 전송하는 역할을 한다.

Processor

메세지를 읽고 그냥 보내기만 한다면 별 문제가 없겠지만, 시스템간의 연동에는 메세지를 받은 후에 수신 시스템으로 보내기전에 하다못해 로깅을 남기더라도 무엇인가 항상 처리를 한다. 이렇게 송신 시스템으로 부터 받은 메세지를 수신 시스템에 보내기전에 무엇인가 처리를 하는 부분을 Processor라고 하는데, Processor는 그 특징에 따라서 몇가지로 나뉘어 질 수 있다.

1. Message Transformation

Message Format Transformation

메세지의 포맷을 변경하는 작업을 수행한다. 예를 들어 JSON으로 들어온 데이타를 XML로 변경하는 것들이 이에 해당한다.

Message Type Transformation

메세지의 데이타 타입을 변경한다. String으로 들어온 메세지를 jms:TextMessageType으로 변경하는 등의 작업을 수행한다.

이러한 메세지 변환은 Java Class를 정의해서할 수 있으며, 이외에도 Camel에서 미리 제공되는 Converter, XSLT를 이용한 변환 Apache Velocity의 같은 Template 엔진등 다양한 방법을 이용해서 변환이 가능하다.

2. Routing

메세지 라우팅은 들어온 메세지를 다수의 수신 시스템에 조건에 따라서 라우팅할 수 있는 기능이다.


Processor 단계는 쉽게 생각하면, 메세지를 받은 후, 보내기전에 무엇인가.. 를 하는 곳이다. 앞서 설명한것처럼, 메세지를 변환하거나, 라우팅할 수 도 있고, 로깅을 할 수도 있다. 들어온 메세지에 대해서 유효성 검증을 할 수 도 있다. 이러한 Processor는 자주 사용되는 메세지 변환등의 패턴은 Camel에 의해서 제공되지만, Java 클래스를 구현하면, 무엇이든지 가능하기 때문에 메세지에 대한 거의 모든 처리를 구현할 수 있는 단계이다.

 

이렇게, “송신 Component à Processor à 수신 Component”로 하나의 Route가 정의되는데, 이렇게 Route를 정의하여 객체화 시키는 것이 RouteBuilder이다. 이렇게 RouteBuilder에 의해서 생성된 Route CamelContext에 바인딩이 된다. CamelContext SpringContext와 유사한 개념으로 생각하면 된다. Route에 대한 집합이며, Route에 대한 라이플 사이클 (Start up,Stop)등을 관리한다.

간단한 개발 예제

이쯤에서 간단한 예제를 하나 보자. 다음은 FTP로 원격지 디렉토리의 파일을 읽어서 Local Directory에 쓰는 Camel Application이다.

먼저 Maven을 이용해서 다음과 같이 Camel Project를 만든 후에,

mvn archetype:create -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=2.5.0 -DgroupId=camelinaction -DartifactId=order-router

다음과 같은 코드를 구현한다.

public class MyRouteBuilder extends RouteBuilder {

    public static void main(String... args) throws Exception {

        Main.main(args);

    }



    public void configure() {

        from("ftp://userid@168.1.2.3/camel/src/?password=password&stepwise=false")

         .to("file:c:/temp/");

 

    }

}

위의 코드는 RouteBuilder를 구현한 코드로 configure 메서드에서 FTP로 파일을 읽어와서 Local에 저장하는 route를 정의한 예이다.

DSL

눈치가 빠른 사람이라면, 위의 코드가 몬가 이상하다는 것을 느꼈을지도 모르겠다. configure 메서드안에 from(“….”).to(“….”).??

함수().함수() 호출? Java에서 이런 문법이 있었던가?

정확히 이야기 하면 이건 일반적인 Java Coding이 아니라 DSL (Domain Specific Language)이다. DSL은 특수목적으로 정의된 언어를 이야기 하는데, 여기서 사용된 Java DSL Route를 효율적으로 정의하기 위해서 Camel에 정의된 내장 스크립트 언어이다.

JavaDSL을 이용하면 상당히 쉽게 Route를 구성할 수 있는데, Camel은 이 Java DSL 뿐만 아니라, 다음과 같이 상당히 다양한 DSL을 제공한다.

Ÿ   Spring XML : XML 기반으로 정의된 DSL , Spring xml configuration 파일에 정의

Ÿ   Groovy,Scala DSL : Groovy 언어, Scala 언어 기반의 DSL

Ÿ   Annotation DSL : Java Annotation 기반의 DSL

Ÿ   기타 (Kotlin DSL, Bluprint XML etc)

(참고: http://camel.apache.org/dsl.html)

DSL Route Processor 부분을 정의하는데 주로 사용되는데, 송수신, Component만 정의되면, 사실상 시스템 연계에서 구현해야 되는 부분은 거의 Processor이며, Processor의 로직 대부분은 메세지 처리, 변환,라우팅에 해당하는 내용이기 때문에 특수목적의 DSL을 사용할 수 있으며, 또한 DSL 사용을 통해서 개발 생산성이나 코드양을 획기적으로 줄일 수 있다.

예를 메세지를 스트링으로 받아서 reverse하여, 화면에 출력하는 경우 Java DSL을 이용하면

from("direct:test")

      .transform(new Expression() {

         @Override

         public Object evaluate(Exchange e) {

            return new StringBuffer(e.getIn().getBody().toString()).reverse().toString();

         }

      })

      .process(new Processor() {

         @Override

         public void process(Exchange e) {

           System.out.println(e.getIn().getBody());

         }

      });

인데 반해서, Groovy DSL을 사용하면

from('direct:test')

      .transform { it.in.body.reverse() }

      .process { println it.in.body }

같이 단지 3줄이면 간단하게 끝난다.

Camel EIP

시스템 연동에는 사실 많은 패턴들이 있다. 메세지 변환, 라우팅, 로그 추적을 위한 글로벌 트렌젝션 ID, 장애시 재처리등등 여러가지 방법이 있는데, 이를 패턴화 시켜놓은 것이 Enterprise Integration Pattern (EIP)이다. EIP


책에 잘 정의 되어 있으니 참고하기 바란다.

사실 Camel에서 반영 및 설계되어 있는 EIP도 이 책에 있는 내용을 대부분 바탕으로 하여 구현되어 있다. (Camel을 쓸려면 이책은 꼭 한번 읽어봐야 하지 않을까 싶다.)

 

참고 : http://camel.apache.org/enterprise-integration-patterns.html 에 간단하게 대표적인 EIP 들이 정리되어 있다.

상용 지원

오픈소스가 무료이라서 저 비용의 장점을 가지고 있지만, 반대로, 오픈소스는 기술지원이나 교육 부분에서 매우 취약하다. 그래서 RedHat과 같이 오픈소스 제품에 대해서 subscription base로 기술 지원이나 교육 및 컨설팅을 제공하는 회사들이 존재하는데, Apache Camel 역시 http://fusesource.com/ 는 곳에서 상용 기술 지원을 받을 수 있다. (얼마전에 Redhat에 인수되었다.) Fuse Source의 경우, Camel을 이용하여 제품을 만들어서 판매하고 있으며, Camel 프로젝트에 참여하고 있는 Commiter 들을 많이 보유하고 있다고 한다.

http://fusesource.com/products/enterprise-camel/ 들어가면 Fuse Source에서 개발 및 판매하는 상용 Camel을 다운로드 받을 수 있으며, 개발 관련 및 트레이닝 자료들을 살펴볼 수 있다.

결론

짧은 시간내에 살펴본 제품이라서 아직 완벽한 특성은 파악하지는 못했다. 그러나 EAI, ESB와 같이 메세지 기반의 연동 처리를 하기 위한 시스템을 개발한다면, 개발 프레임웍으로 충분히 활용할만 하다. 특히 엔터프라이즈의 특정 애플리케이션 (ERP,CRM)등이 아니라 일반적인 프로토콜 (HTTP,JMS,TCP)등을 사용하여 그리 복잡하지 않으면서 고속의 연동 처리를 필요로 한다면 아주 유용하게 사용할 수 있을 것이라 판단된다.

시간 관계상 에러처리, 모니터링, 배포 및 확장성등 운영 관점에 대한 부분은 깊게 살펴보지 못했지만, 그냥 개발 프레임웍으로 본다면, 어짜피 운영 관련 부분은 직접 구현해야 하니까는 괜찮지 않을까 싶다.

다만 단순히 프레임웍이기 때문에, 클러스터링 기반의 HA나 부하 분산등의 기능을 제공하지 않는 것이 아쉬운 점이다.

시스템간의 연동의 중요성과 편이성을 경험한 나한테는, Apache Camel물건은 물건이다.” 라는 결론이 적절하다고나 할까?

 

ErrorHandling - http://bcho.tistory.com/716


참고:ErrorHandling에 대한 관련글 -

http://www.consulting-notes.com/2010/08/camel-exception-handling-overview.html 

정리가 잘되어 있네...

 

'아키텍쳐  > EAI' 카테고리의 다른 글

Apache Camel Error Handling  (0) 2013.02.20
Apache Camel Overview  (0) 2013.02.17
EAI (Enterprise Application Integration) 추진 전략  (2) 2009.07.16
ETL vs EAI  (0) 2009.06.16
EAI 도입 전략  (0) 2007.08.21

Apache Camel note

엔터프라이즈 솔루션 | 2013.02.12 19:10 | Posted by 조대협

1. 프로젝트 생성하기

mvn archetype:create -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=2.5.0 -DgroupId=camelinaction -DartifactId=order-router


으로  Camel Project 생성

2. 코드 
아래는 Spring을 이용하여, FTP로 파일을 읽어서 Local의 C:\temp에 복사하는 코드

public class MyRouteBuilder extends RouteBuilder {

    /**
     * A main() so we can easily run these routing rules in our IDE
     */
    public static void main(String... args) throws Exception {
        Main.main(args);
    }

    /**
     * Lets configure the Camel routing rules using Java code...
     */
    public void configure() {
        from("ftp://userid@168.1.2.3/camel/src/?password=password&stepwise=false")
        .to("file:c:/temp/");

    }
}


'엔터프라이즈 솔루션' 카테고리의 다른 글

Apache Camel note  (0) 2013.02.12
아키텍쳐에 있어서 레퍼런스의 중요성  (2) 2009.10.20
2009년 기술 전망  (2) 2009.01.06