[원문출처] https://camel.apache.org/components/2.x/aws-s3-component.html

 

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

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

 

(주) 소곰소프트

GS인증 획득 (주)소곰소프트의 Sogom ISB 1.2.0(ESB:Enterpries Service Bus)제품이 한국정보통신기술협회(TTA)의 소프트웨어 품질인증인 Good Software 1등급 인증을 획득하였습니다. GS 인증은 국가가 국산 소프

www.sogomsoft.co.kr

Amazon S3 스토리지 서비스 컴포넌트

Camel 2.8 이후 지원, Both producer 와 consumer 양쪽 모두 지원.

S3 컴포넌트는 Amazon’s S3 서비스에 또는 서비스로 부터 객체를 저장하거나 조회 하는 것을 지원한다.

전제 조건으로 유효한 Amazon Web Services 개발자 계정을 가지고 있어야 하고,  S3에 가입되어 있어야 한다.  Amazon S3에서 더 많은 정보를 볼 수 있다.

URI 형식

aws-s3://[bucketName|arn][?options]

이 버킷은 만약 존재 하지 않는다면 생성되게 될 것이다. ?options=value&option2=value&… 과 같은 형식으로 URI에 쿼리 옵션을 추가 할 수있다. 

예를 들면,  helloBucket 버킷으로 부터 hello.txt 파일을 읽기 위해, 다음처럼 사용한다. :

from("aws-s3://helloBucket?accessKey=yourAccessKey&secretKey=yourSecretKey&prefix=hello.txt")
  .to("file:/var/downloaded");

 

환경 구성 옵션

환경 구성 옵션은 다음과 같이 2레벨로 구분된 레벨로 환경 설정 될 수 있다. 

  • 컴포넌트 레벨
  • 엔드포인트 레벨

환경 구성 컴포넌트 옵션

컴포넌트 레벨은 엔드포인트에 의해 상속받게 되는 일반적이고 보통의 환경 구성을 설정하기 위한 가장 높은 레벨이다. 컴포넌트의 보안 설정, 인증을 위한 자격증명, 네트워크 연결을 위한 URL 등과 같은 것을 설정한다. 

환경 구성 엔드포인트 옵션

가장 많이 자체적으로 환경 구성하는 곳이 엔드포인트이고, 엔드포인트가 종종 많은 옵션을 가지고, 엔드포인트에 해야 할 필요가 있는 환경 설정하는 것을 허용한다.  이 옵션은 엔드포인트가 컨슈머로서, 프로듀서로서 또는 양쪽 모두에서 사용되는 지에 따라 분류 된다.

 

컴포넌트 옵션

AWS S3 스토리지 서비스 컴포는트는 아래 목록에 나열된 것처럼 39가지옵션을 제공한다. 

이름 상세설명 기본값 유형
configuration 
(common)
컴포넌트의 환경 구성을 한다.   S3Configuration
region 
(common)
S3 클라이언트가 작업할 필요가 있는 리즌. 이 파라미터를 사용할 때, 환경구성에서 리즌의 대문자 이름을 예상하게 될 것이다. (예를 들면, AP_EAST_1) Regions.EU_WEST_1.name() 메서드로 이름을 사용해야 할 것이다.    String
resolvePropertyPlaceholders
(advanced)
시작할 때, 자체적으로 프로퍼티 플레이스홀더를 해결해야 하는지 여부를 설정한다. 단지 문자열 유형으로 된 프로퍼티들만 프로퍼티 플레이스 홀더를 사용 할 수 있다. true boolean
accessKey 
(security)
아마존 AWS 엑세스 키   String
secretKey 
(security)
아마존 AWS 시크릿 키   String

 

엔드포인트 옵션 

 AWS S3 저장소 서비스 엔드포인트는 다음 URI 구문을 사용하여 환경 구성될 수 있다. :

aws-s3://bucketNameOrArn

다음 패스 파라미터와 와 쿼리 파라미터를 사용하여 :

패스 파라미터 (1개 파라미터):

이름 상세설명 기본값 타입
bucketNameOrArn 필수값 버킷명 또는ARN(Amazon Resource Number, 아마존 리소스 번호)   String

 

쿼리 파라미터 (58개 파라미터):

이름 상세설명 기본값 타입
amazonS3Client 
(common)
레지스터리에서 com.amazonaws.services.s3.AmazonS3 에 참조 된다..   AmazonS3
pathStyleAccess 
(common)
S3 클라이언트가 패스 스타일을 사용하는지 아닌지를 설정한다.  false boolean
policy 
(common)
com.amazonaws.services.s3.AmazonS3#setBucketPolicy() 메서드에서 설정할 큐를 위한 정책을 설정한다.   String
proxyHost 
(common)
S3 클라이언트를 인스턴스화 할때 프록시 호스트를 정의한다.   String
proxyPort 
(common)
S3 클라이언트 정의 내부에 사용될 프록시 포트를 지정한다.   Integer
region 
(common)
S3 클라이언트가 작업할 필요가 있는 리즌. 이 파라미터를 사용할 때, 환경구성에서 리즌의 대문자 이름을 예상하게 될 것이다. (예를 들면, AP_EAST_1) Regions.EU_WEST_1.name() 메서드로 이름을 사용해야 할 것이다.    String
useIAMCredentials 
(common)
S3 클라이언트가 EC2 인스턴스에 자격증명을 로드 하는 것을 기대하는지 또는 통과되기 위한 정적 자격 증명을 기대 해야 하는지를 설정한다. false boolean
encryptionMaterials 
(common)
클라이언트가 사용할 대칭/비대칭의 경우에 사용하게 될 암호화 자료   EncryptionMaterials
useEncryption 
(common)
암호화를 사용할 것인지 아닌지를 정의 한다. false boolean
bridgeErrorHandler 
(consumer)
Camel 라우팅 에러 핸들러에 컨슈머를 연결하는 것을 허용한다. 이는 어떤 예외가 발생했을 때, 컨슈머가 들어오는 메시지 또는 선호하는 것을 가져오는 것을 시도 하는것을 의미 한다. 라우팅 에러 핸들러에 의해 메시지가 처리 하고 관리 되게 될 것이다. 기본값은 컨슈머가 예외를 다루기 위해 org.apache.camel.spi.ExceptionHandler를 사용하게 될 것이고, WARN 또는 ERROR 레벨로 로깅 되거나 무시 될 것이다.  false boolean
deleteAfterRead 
(consumer)
이 옵션은 조회된 이후에 S3로 부터 객체를 지운다. 이 삭제는 단지 Exchange가 커밋되었을 때 수행되게 된다. 만약 롤백이 발생하면 이 객체는 지워지지 않는다. 이 옵션이 false이면, 메시지를 폴링시에 계속 계속 조회 되게 될 것이다. 그러므로 라우터에서 중복을 필터링하기 위해 멱등적 컨슈며 EIP를 사용할 필요가 있다. S3Constants#BUCKET_NAME 과 S3Constants#KEY 헤더 또는 S3Constants#KEY 헤더를 사용하여 필터링 할 수 있다 . true boolean
fileName 
(consumer)
주어진 파일 명으로 버킷에서 객체를 얻기위해 사용한다.   String
includeBody 
(consumer)
이 옵션이 true이면, exchange 바디에 파일의 내용을 스트림으로 설정되게 되고 false이면, 헤더에 S3 객체 메타 데이타로 설정되게 되고 바디 값은 null이 된다. 이 옵션은 autocloseBody 옵션과 밀접한 관련 되어 있다. includeBody가 true로 설정된 경우에, autocloseBody가 false이면, S3Object 스트림을 닫는 것은 호출자에 달려 있다. autocloseBody가 true 설정되어 있으면, S3Object 스트림이 자동으로 닫히게 될 것이다. true boolean
maxConnections 
(consumer)
S3 클라이언트 환경 구성에서 최대 커넥션 파라미터를 설정한다. 60 int
maxMessagesPerPoll
(consumer)
각각을 폴링 시 폴링하기 위한 제한으로 메시지의 최대 수를 얻는다. 기본 값은 10이고. 제한없도록 설정하기 위해서는 0 또는 음수를 설정한다. 10 int
prefix 
(consumer)
이 옵션은 관심 있는 객체를 소비 하기 위해 com.amazonaws.services.s3.model.ListObjectsRequest에서 사용될 접두사이다.   String
sendEmptyMessageWhenIdle 
(consumer)
만약 폴링 컨슈머가 어떤 파일을 폴링 하지 않는다면, 대신 비어있는 메시지(no body)를 보내기 위해서 이 옵션을 활성화 할 수 있다. false boolean
autocloseBody 
(consumer)
만약 이 옵션이 true 이고 includeBody가 true이면, S3Object.close() 메서드가 exchange가 완료시 호출 되게 될 것이다. 이 옵션은 includeBody 옵션에 밀접하게 관련되어 있다. includeBody가 true로 설정된 경우에, autocloseBody가 false이면, S3Object 스트림을 닫는 것은 호출자에 달려 있다. autocloseBody가 true 설정되어 있으면, S3Object 스트림이 자동으로 닫히게 될 것이다.
true boolean
exceptionHandler 
(consumer)
컨슈며가 사용자 정의 ExceptionHandler를 사용하게 한다.  만약 bridgeErrorHandler 옵션이 활성화 되어 있다면 이 옵션이 사용되지 않는다는 점에 유의하라. 기본적으로 컨슈머는 예외를 처리 하게 되고, WARN 나 ERROR 레벨로 로그릴 기록하게 되거나 무시되게 될 것이다.    ExceptionHandler
exchangePattern 
(consumer)
컨슘가 Exchange를 생성할 때, Exchange 패턴을 설정한다. 3개의 열거형으로 구성되어 있고 InOnly, InOut, InOptionalOut 중에 하나가 될 수 있다.   ExchangePattern
pollStrategy 
(consumer)
Camel에서 Exchange가 생성되고 라우팅 되기 전에 폴링 동작을 하는 동안 에러를 핸들링을 컨트롤 하기 위해 사용자 정의 구현체를 제공하기 위해 하용하고 있는 플러그인 가능한 org.apache.camel.PollingConsumerPollingStrategy 을 설정한다.    PollingConsumerPollStrategy
deleteAfterWrite 
(producer)
이 옵션은 S3 파일이 업로드 되었을 때 파일 객체를 삭제한다. false boolean
multiPartUpload 
(producer)
만약 true이면, multi part 형식으로 파일을 업로드 하게 될 것이다. 이 멀티파트의 사이즈는 partSize 옵션에 의해 결정되게 된다. false boolean
operation 
(producer)
단지 업로드만 원하지 않는 경우에 사용하기 위한 작업이다. copyObject, deleteBucket, listBuckets, downloadLink 의 4개의 열거형이 있고 그중에 하나의 값을 선택 할 수 있다.   S3Operations
partSize 
(producer)
multi part 업로드에서 사용할 partSize를 설정한다 기본값은 25M이다. 26214400 long
serverSideEncryption 
(producer)
AWS에서 관리되는 키로 객체를 암호화 하기 위해서 서버 측 암호화 알고리즘을 설정한다. 예를 들면 AES256.   String
storageClass 
(producer)
com.amazonaws.services.s3.model.PutObjectRequest 요청에서 설정할 저장소 클래스를 지정한다.   String
awsKMSKeyId 
(producer)
KMS가 활성화 된 경우에 사용할 KMS 키의 ID를 정의 한다.    String
useAwsKMS 
(producer)
KMS 사용해야 하는지 아닌지를 정의한다. false boolean
accelerateModeEnabled 
(advanced)
가속 모드(Accelerate Mode)를 true인지 false인지를 정의한다. false boolean
chunkedEncodingDisabled 
(advanced)
비활성화 된 청크 인코딩이 true인지 false인지를 정의한다. 
HTTP 1.1 version 에서 사용가능한 스트리밍 데이터 전송 방식, 
chunked 인코딩 방식에서 데이터는 각각의 덩어리들 나눠 독립적으로 송신 및 수신 ,
각 chunk의 앞에는 해당 chunk의 크기 설정 형식은 byte 형식으로 송수신
길이가 0인 chunk가 수신되면 전송이 종료
false boolean
dualstackEnabled 
( advanced)
듀얼스택이 활성화가 true인지 false인지를 정의한다. false boolean
forceGlobalBucketAccessEnabled 
( advanced)
강제 글로벌 버킷 엑세스(Force Global Bucket Access)이 활성화가 true인지 false인지를 정의한다. false boolean
payloadSigningEnabled 
( advanced)
페이로드 서명(Payload Signing)이 활성화가 true인지 false인지를 정의한다. false boolean
backoffErrorThreshold 
(scheduler)
backoffMultipler 시작 되기 전에 발생되어야 하는 (어떤 에러로 실패된) 에러 폴링의 하위순번의 숫자.   int
backoffIdleThreshold 
(scheduler)
backoffMultipler 시작 되기 전에 발생되어야 하는 유휴 홀링의 하위 순번의 숫자   int
backoffMultiplier 
(scheduler)
To let the scheduled polling consumer backoff if there has been a number of subsequent idles/errors in a row.
개별 행의 유휴/에러 하위순번의 숫자를 가지고 있다면 예약된 폴링 컨슈며가 물러나게 한다.
multiplier는 다음 실제 시도가 다시 발생하기 전에 건너뛰어야 하는 폴링의 수이다. 이 옵션을 사용할 때는 backoffIdleThreshold 나/또는 backoffErrorThreshold가 반드시 환경 구성 되어 있어야 한다.
  int
delay 
(scheduler)
다음 폴링 전에 지연 시간(밀리초). 500 long
greedy 
(scheduler)
greedy 옵션이 활성화 되어 있다면, 이전 실행이 하나 또는 그 이상의 메시지를 폴링한 경우, ScheduledPollConsumer가 즉시 다시 실행되게 된다.  false boolean
initialDelay 
(scheduler)
첫번째 폴링 시작 전에 지연시간(밀리초). 1000 long
runLoggingLevel 
(scheduler)
컨슈며가 폴링 될 때, 시작/완료 로그 라인을 로그 기록한다. 이 옵션은 로그를 위한 로그 레벨을 환경 설정하는 것을 허용하고 로그 레벨은 6개의 열거형으로 되어 있고 TRACE, DEBUG, INFO, WARN, ERROR, OFF 값중에 하나를 사용한다.  TRACE LoggingLevel
scheduledExecutorService 
(scheduler)
컨슈머를 위해 사용할 사용자정의 또는 공유된 쓰레드 풀을 환경 구성하는 것을 허용한다. 기본적으로 각각 컨슈며는 단일 쓰레드로된 자신의 쓰레드 풀을 가지고 있다.    ScheduledExecutorService
scheduler 
(scheduler)
camel-spring 또는 camel-quartz 컴포넌트로부터 크론 스케줄을 사용하기 위해서 설정. 스케줄러에서 내장된 스프링 또는 쿼츠의 값을 사용한다.  none Object
schedulerProperties 
(scheduler)
사용자 정의 스케줄러 또는 쿼츠나 스프링 기반 스케줄러 중에 하나를 사용할때 추가적인 프로퍼티를 환경 구성하기 위해 사용한다.    Map
startScheduler 
(scheduler)
스케줄러가 자동 시작 되어야 하는지를 설정한다. true boolean
timeUnit 
(scheduler)
initialDelay 과 delay 옵션읠 위한 타임 유닛 값. 7개의 열거형을 가지고 NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS 중에 하나의 값이 될 수 있다. MILLISECONDS TimeUnit
useFixedDelay 
(scheduler)
고정된 지연시간 또는 고정된 비율이 사용되었는지를 제어한다. 자세한 것은 JDK의 ScheduledExecutorService 를 보라 true boolean
accessKey (security) 아마존 AWS 엑세스 키   String
secretKey (security) 아마존 AWS 시크릿 키   String
필수 S3 컴포넌트 옵션
레지스터리에 Amazon’s S3에 엑세스 하기 위해  amazonS3Client 또는 액세스 키 와 시크릿 키를 제공 해야 한다. 

 

배치 컨슈머

이 컴포넌트는 배치 컨슈머를 구현한다.

인스턴스가 배치에 존재 하는 메시지가 얼마나 많은지 알 수 있고 Aggregator가 메시지의 수를 집계 하게 해주는 것을 허용한다. 

S3 컴포넌트 사용예

S3 프로듀서에 의해 사용될 메시지 헤더
 
헤더 유형 상세 설명
CamelAwsS3BucketName String 현재 작업에서 저장되거나 사용되게 될 객체의 버킷 이름.
CamelAwsS3BucketDestinationName String 현재 작업에서 사용되게 될 버킷 목적지 명.
CamelAwsS3ContentLength Long 이 객체의 컨텐츠 길이.
CamelAwsS3ContentType String 이 객체의 컨텐츠 유형.
CamelAwsS3ContentControl String 이 객체의 컨텐츠 컨트롤
CamelAwsS3ContentDisposition String 이 객체의 컨텐츠 처분
CamelAwsS3ContentEncoding String 이 객체의 컨텐츠 인코딩
CamelAwsS3ContentMD5 String 이 객체의 md5 체크섬
CamelAwsS3DestinationKey String 현재 작업에서 사용되게 될 목적지 키.
CamelAwsS3Key String 현재 작업에서 저장되거나 사용되게 될 아래 키.
CamelAwsS3LastModified java.util.Date 이 객체의 마지막 변경된 타임스탬프.
CamelAwsS3Operation String 수행할 작업. 허용되는 값은 copyObject, deleteObject, listBuckets, deleteBucket, downloadLink, listObjects 이다.
CamelAwsS3StorageClass String 객체의 저장 클래스
CamelAwsS3CannedAcl String 객체에 적용하게 될 취소된 acl. 허용되는 값은 com.amazonaws.services.s3.model.CannedAccessControlList를 보라.
CamelAwsS3Acl com.amazonaws.services.s3.model.AccessControlList 맞게 생성된 Amazon S3 Access Control List 객체. 더 자세한 것은 com.amazonaws.services.s3.model.AccessControlList를 보라.
CamelAwsS3Headers Map<String,String> 사용자 정의 objectMetadata 헤더들을 얻거나 설정하는 것을 지원한다..
CamelAwsS3ServerSideEncryption String AWS에 관리되는 키를 사용하여 객체를 암호화 할 때, 서버측 암호화 알고리즘을 설정한다. 예를 들면, AES256를 사용.
CamelAwsS3VersionId String 현재 작업으로 부터 저장되거나 반환될 객체의 버전 ID

S3 프로듀서에 의해 설정될 메시지 헤더

헤더 유형 상세 설명
CamelAwsS3ETag String 새로 업로드 될 객체를 위한 ETag 값.
CamelAwsS3VersionId String 새로 업로드 될 객체의 부가적인 버전 ID.
CamelAwsS3DownloadLinkExpiration String URL 다운로드 링크의 만료 시간(밀리초). 다운로드 링크는 CamelAwsS3DownloadLink 응답 헤더에 저장되게 될 것이다.

S3 컨슈머에 의해 설정될 메시지 헤더

헤더 유형 상세 설명
CamelAwsS3Key String 객체가 저장 될 때 키
CamelAwsS3BucketName String 객체가 포함된 버킷의 이름.
CamelAwsS3ETag String RFC 1864에 따라 객체와 관련된 16진수로 인코딩된 128-bit MD5 다이제스트. 이 데이타는 호출자가 수신 받은 데이타와 아마존 S3에 의해 보내 질 데이타와 같은지 검증하기 위해 무결성 체크로 사용된다. 
CamelAwsS3LastModified Date 객체와 관련해서 아마존 S3 마지막 기록된 변경 사항에 날짜와 시간을 나타내는 마지막 변경 시점 헤더의 값
CamelAwsS3VersionId String 만약 가능하다면 연관된 아마존 S3 객체 버전 ID. 버전 ID들은 객체 버전 관리가 활성화 된 Amazon S3 버킷에 객체가 업로드 될 때,  객체에만 할당 된다.
CamelAwsS3ContentType String 연관된 객체에 저장될 컨텐츠의 유형을 가리키는 Content-Type HTTP 헤더. 이 헤더의 값은 표준 MIME 유형이다.
CamelAwsS3ContentMD5 String RFC 1864에 따라연관된 객체의 base64 인코딩된 128-bit MD5 다이제스트. (헤더를 포함하지 않는 컨텐츠). 이 데이타는 Amazon S3에 의해 수신 된 데이타가 호출자에게 보내진 데이타와 같은지를 검증하기 위해 무결성 체크 메시지로 사용된다. 
CamelAwsS3ContentLength Long byte로 객체와 연관된 사이즈를 나타내는 Content-Length HTTP 헤더.
CamelAwsS3ContentEncoding String 객체에 적용된 컨텐츠 인코딩이 무엇인지, Content-Type 필드에 의해 참조될 미디어 타입을 포함하기 위해 적용되어야 하는 디코딩 매카니즘이 무엇인지를 지정하는 부가적인 Content-Encoding HTTP 헤더.
CamelAwsS3ContentDisposition String 저장될 객체를 위한 요청되어진 파일 명 같은 프리젠테이션 정보를 지정하는 부가적인 Content-Disposition HTTP 헤더.
일반적인 HTTP 응답에서 Content-Disposition 헤더는 컨텐츠가 브라우저에 inline 되어야 하는 웹페이지 자체이거나 웹페이지의 일부인지, 아니면 attachment로써 다운로드 되거나 로컬에 저장될 용도록 쓰이는 것인지를 알려주는 헤더입니다
CamelAwsS3ContentControl String 사용자가 HTTP 요청/응답 체인을 따라 캐싱 동작을 지정하는 것을 허용하는 부가적인 Cache-Control HTTP 헤더. 
CamelAwsS3ServerSideEncryption String AWS에 의해 관리되는 키를 사용하여 객체를 암호화 할때 서버측 암호화 알고리즘.

S3 프로듀셔 작업

Camel-AWS s3 컴포넌트는 프로듀서 측에서 다음 작업을 제공한다. :

  • copyObject
  • deleteObject
  • listBuckets
  • deleteBucket
  • downloadLink
  • listObjects
  • getObject (S3Object 인스턴스를 반환하게 될 것이다.)
  • getObjectRange ( S3Object 인스턴스를 반환하게 될 것이다.)

고급 아마존 S3 환경 구성

만약 Camel 어플리케이션이 방화벽 뒤에서 동작중이거나 또는 아마존 S3 인스턴스 환경 구성을 좀더 컨트롤 하는 것을 원하면 자신의 환경 구성 인스턴스를 생성 할 수 있다. :

AWSCredentials awsCredentials = new BasicAWSCredentials("myAccessKey", "mySecretKey");

ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setProxyHost("http://myProxyHost");
clientConfiguration.setProxyPort(8080);

AmazonS3 client = new AmazonS3Client(awsCredentials, clientConfiguration);

registry.bind("client", client);

Camel aws-s3 컴포넌트 환경구성 설정을 참조한다.:

from("aws-s3://MyBucket?amazonS3Client=#client&delay=5000&maxMessagesPerPoll=5")
.to("mock:result");

S3 컴포넌트로 KMS 사용하기

To use AWS KMS to encrypt/decrypt data by using AWS infrastructure you can use the options introduced in 2.21.x like in the following example

from("file:tmp/test?fileName=test.txt")
     .setHeader(S3Constants.KEY, constant("testFile"))
     .to("aws-s3://mybucket?amazonS3Client=#client&useAwsKMS=true&awsKMSKeyId=3f0637ad-296a-3dfe-a796-e60654fb128c");

In this way you’ll ask to S3, to use the KMS key 3f0637ad-296a-3dfe-a796-e60654fb128c, to encrypt the file test.txt. When you’ll ask to download this file, the decryption will be done directly before the download.

S3 컴포넌트로 IAM자격증명사용 옵션 ("useIAMCredentials" ) 사용하기

아마존 IAM 자격증명을 사용하기 위해, 먼저 Camel 어플리케이션을 구동하고 있는 EC2가 효과적으로 동작하기 위해 첨부된 적절한 정책을 포함된 것과 관련된 IAM 롤을 가지는지를 검증 해야 한다.  단지 이 기능은 원격 인스턴스에 "true" 를 설정해야 한다는 것을 유의해라. 심지어 더 명확하기 위해, IAM 가  AWS 특정 컴포넌트이기 때문에 로컬환경에서는 정적 자격증명을 여전히 사용해야 하고, 그러나 AWS 환경은 더 휩게 관리 되어야 한다. 이 IAM 자격 증명이 구현되고 이해 되었을 때,  AWS 환경 설정을 위해, 쿼리 파리미터 "useIAMCredentials"에 "true"로 설정 할 수 있다.  로컬 환경과 원격 환경에 기반하여 on/off로 효과적으로 전환 하기 위해, 시스템 환경 변수로 쿼리 파라미터를 활성화 하는 것을 고려 할 수 있다. 예를 들면, "isRemote" 가 "true"로 시스템 환경 변수에서 호출 될 때, 당신의 코드에 쿼리 파라미터에 "true" 를 설정해야 한다. ( 간단한 예제처럼 동작해야 하고 그렇게 하기 위한 많은 다른 방법이 있다). 비록 정적 자격 증명이 완전하게 필요가 제거 되지 않는다 할지라도, 마마존 AWS 환경 설정에서 IAM credentials을 사용하는 것은 원격 환경에서 갱신될 필요를 없애고, 주요 보안이 향상을 추가 한다.  (IAM 자격증명은 매일 6시간 마다 자동적으로 갱신되고 그 보안 정책이 업데이트 될때 업데이트 된다). 이것은 가격 증명을 관리 하기 위해 AWS에서 요구된 방법이고 그러므로 가능한 자주 사용해야 한다. 

S3 PRODUCER OPERATION EXAMPLES

  • CopyObject: 이 동작은 하나의 버킷으로 부터 다른 하나의 버킷으로 객체를 복사 한다. 
  from("direct:start").process(new Processor() {

      @Override
      public void process(Exchange exchange) throws Exception {
          exchange.getIn().setHeader(S3Constants.BUCKET_DESTINATION_NAME, "camelDestinationBucket");
          exchange.getIn().setHeader(S3Constants.KEY, "camelKey");
          exchange.getIn().setHeader(S3Constants.DESTINATION_KEY, "camelDestinationKey");
      }
  })
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=copyObject")
  .to("mock:result");

이 옵션은 객체를 camelDestinationKey 헤더에서 표현된 이름으로 mycamelbucket 버킷으로 부터  to the camelDestinationBucket 버킷로 복사한다.

  • DeleteObject: 이 작업은 버킷으로 부터 객체를 삭제 한다. 
  from("direct:start").process(new Processor() {

      @Override
      public void process(Exchange exchange) throws Exception {
          exchange.getIn().setHeader(S3Constants.KEY, "camelKey");
      }
  })
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObject")
  .to("mock:result");

이 작업은 mycamelbucket 버킷으로 부터 camelKey 객체를 삭제 하게 된다.

  • ListBuckets: 이 작업은 이 리즌 내의 계정에 버킷의 목록을 나열한다.
  from("direct:start")
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=listBuckets")
  .to("mock:result");

이 작업은 이 계정의 버킷들의 목록을 나열하게 될 것이다. 

  • DeleteBucket: 이 작업은 URI 파라미터와 헤더로 지정된 버킷을 삭제 한다. 
  from("direct:start")
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteBucket")
  .to("mock:result");

이 작업은 mycamelbucket 버킷을 삭제 한다.

  • DownloadLink: 이 작업은 키 헤더에 지정된 파일을 위한 다운로드 링크를 생성한다. 
  from("direct:start").process(new Processor() {

      @Override
      public void process(Exchange exchange) throws Exception {
          exchange.getIn().setHeader(S3Constants.KEY, "camelKey");
      }
  })
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=downloadLink")
  .to("mock:result");

이 작업은 mycamelbucket 버킷에 camelKey의 파일을 위한 다운로드 링크를 생성한다.

  • ListObjects: 이 작업은 지정된 버킷에 객체를 목록으로 나열한다. 
  from("direct:start")
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=listObjects")
  .to("mock:result");

이 작업은 mycamelbucket 버킷에 객체 목록을 나열하게 될 것다.

  • GetObject: 이 작업은 지정된 버킷에 단일 객체를 얻게 된다. 
  from("direct:start").process(new Processor() {

      @Override
      public void process(Exchange exchange) throws Exception {
          exchange.getIn().setHeader(S3Constants.KEY, "camelKey");
      }
  })
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObject")
  .to("mock:result");

이 작업은 mycamelbucket 버킷에서 camelKey 객체에 관련된 S3Object를 반환하게 될 것이다..

  • GetObjectRange: 이 작업은 지정된 버킷에서 단일 범위 객체를 얻는다. 
  from("direct:start").process(new Processor() {

      @Override
      public void process(Exchange exchange) throws Exception {
          exchange.getIn().setHeader(S3Constants.KEY, "camelKey");
          exchange.getIn().setHeader(S3Constants.RANGE_START, "0");
          exchange.getIn().setHeader(S3Constants.RANGE_END, "9");
      }
  })
  .to("aws-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectRange")
  .to("mock:result");

이 작업은 0에서 9까지 바이트들을 포함하는 mycamelbucket 버킷에 camelKey 객체에 관련된 S3Object 인스턴스를 반환한다.

버킷 자동 생성

autoCreateBucket 옵션으로, 사용자는S3 버킷이 존재 하지 않는 경우에 자동 생성을 피할 수 있다. 이 옵션의 기본값은 true 이다. 만약 false로 설정되면, AWS 내에 존재 하지 않은 모든 버킷에 대한 어떤 동작도 성공할 수 없고 에러를 반환하게 될 것이다. 

레지스터리 에서 Amazon S3 클라이언트 자동 탐색 

이 컴포넌트는 레지스터리에서 Amazon S3 빈의 존재를 탐색하는 것이 가능하다.  만약 Amazon S3 클라이언트 유형의 유일한 인스턴스라면 그 인스턴스를 클라이언트로 사용하게 될 것이고, 예제에서 처럼 uri 파라미터로 S3 클라이언트를 정의 할 필요는 없다. 이는 엔드포인트의 스마트하게 환경구성하기 위해 더 유용할 수 있다. 

하나의 버킷에서 다른 버킷으로 객체 이동

몇몇 사용자는 이 컴포넌트의  copyObject 기능을 사용하지 않고 어떤 버킷으로 부터 객체를 소비하고 다른 버킷에 컨텐츠를 옮기는 것을 좋아한다. 만약 당신이 이 경우라면, 컨슈머의 들어오는 Exchange로 부터  bucketName 헤더를 제거 하는 것을 잊지 말아라. 그렇지 않으면 그 파일이 같은 원본 버킷을 항상 재 작성 하게 될 것이다. 

디펜던시

메이븐 사용자는 pom.xml 파일에 다음 디펜던시를 추가 해야 할 것이다.

pom.xml

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-aws-s3</artifactId>
    <version>${camel-version}</version>
</dependency>

where ${camel-version} must be replaced by the actual version of Camel.

스프링 부트 자동 환경 구성 

스프링 부트로 aws-s3를 사용할 때 자동 환경 구성을 가지기 위해 메이븐 디펜던시를 다음과 같이 설정 해야 한다.:

<dependency>
  <groupId>org.apache.camel.springboot</groupId>
  <artifactId>camel-aws-s3-starter</artifactId>
  <version>x.x.x</version>
  <!-- use the same version as your Camel core version -->
</dependency>

이 컴포넌트는 아래 나열된 40개 옵션을 지원한다. 

이름 상서 설명 기본값 유형
camel.component.aws-s3.accelerate-mode-enabled Define if Accelerate Mode enabled is true or false. false Boolean
camel.component.aws-s3.access-key Amazon AWS Access Key.   String
camel.component.aws-s3.amazon-s3-client Reference to a com.amazonaws.services.s3.AmazonS3 in the registry. The option is a com.amazonaws.services.s3.AmazonS3 type.   AmazonS3
camel.component.aws-s3.auto-create-bucket Setting the autocreation of the bucket. true Boolean
camel.component.aws-s3.auto-discover-client Setting the autoDiscoverClient mechanism, if true, the component will look for a client instance in the registry automatically otherwise it will skip that checking. true Boolean
camel.component.aws-s3.autoclose-body If this option is true and includeBody is true, then the S3Object.close() method will be called on exchange completion. This option is strongly related to includeBody option. In case of setting includeBody to true and autocloseBody to false, it will be up to the caller to close the S3Object stream. Setting autocloseBody to true, will close the S3Object stream automatically. true Boolean
camel.component.aws-s3.autowired-enabled Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. true Boolean
camel.component.aws-s3.aws-k-m-s-key-id Define the id of KMS key to use in case KMS is enabled.   String
camel.component.aws-s3.bridge-error-handler Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. false Boolean
camel.component.aws-s3.chunked-encoding-disabled Define if disabled Chunked Encoding is true or false. false Boolean
camel.component.aws-s3.configuration The component configuration. The option is a org.apache.camel.component.aws.s3.S3Configuration type.   S3Configuration
camel.component.aws-s3.delete-after-read Delete objects from S3 after they have been retrieved. The delete is only performed if the Exchange is committed. If a rollback occurs, the object is not deleted. If this option is false, then the same objects will be retrieve over and over again on the polls. Therefore you need to use the Idempotent Consumer EIP in the route to filter out duplicates. You can filter using the S3Constants#BUCKET_NAME and S3Constants#KEY headers, or only the S3Constants#KEY header. true Boolean
camel.component.aws-s3.delete-after-write Delete file object after the S3 file has been uploaded. false Boolean
camel.component.aws-s3.delimiter The delimiter which is used in the com.amazonaws.services.s3.model.ListObjectsRequest to only consume objects we are interested in.   String
camel.component.aws-s3.dualstack-enabled Define if Dualstack enabled is true or false. false Boolean
camel.component.aws-s3.enabled Whether to enable auto configuration of the aws-s3 component. This is enabled by default.   Boolean
camel.component.aws-s3.encryption-materials The encryption materials to use in case of Symmetric/Asymmetric client usage. The option is a com.amazonaws.services.s3.model.EncryptionMaterials type.   EncryptionMaterials
camel.component.aws-s3.endpoint-configuration Amazon AWS Endpoint Configuration. The option is a com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration type.   AwsClientBuilder$EndpointConfiguration
camel.component.aws-s3.file-name To get the object from the bucket with the given file name.   String
camel.component.aws-s3.force-global-bucket-access-enabled Define if Force Global Bucket Access enabled is true or false. false Boolean
camel.component.aws-s3.include-body If it is true, the exchange body will be set to a stream to the contents of the file. If false, the headers will be set with the S3 object metadata, but the body will be null. This option is strongly related to autocloseBody option. In case of setting includeBody to true and autocloseBody to false, it will be up to the caller to close the S3Object stream. Setting autocloseBody to true, will close the S3Object stream automatically. true Boolean
camel.component.aws-s3.key-name Setting the key name for an element in the bucket through endpoint parameter.   String
camel.component.aws-s3.lazy-start-producer Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. false Boolean
camel.component.aws-s3.multi-part-upload If it is true, camel will upload the file with multi part format, the part size is decided by the option of partSize. false Boolean
camel.component.aws-s3.operation The operation to do in case the user don’t want to do only an upload.   S3Operations
camel.component.aws-s3.part-size Setup the partSize which is used in multi part upload, the default size is 25M. 26214400 Long
camel.component.aws-s3.path-style-access Whether or not the S3 client should use path style access. false Boolean
camel.component.aws-s3.payload-signing-enabled Define if Payload Signing enabled is true or false. false Boolean
camel.component.aws-s3.policy The policy for this queue to set in the com.amazonaws.services.s3.AmazonS3#setBucketPolicy() method.   String
camel.component.aws-s3.prefix The prefix which is used in the com.amazonaws.services.s3.model.ListObjectsRequest to only consume objects we are interested in.   String
camel.component.aws-s3.proxy-host To define a proxy host when instantiating the S3 client.   String
camel.component.aws-s3.proxy-port Specify a proxy port to be used inside the client definition.   Integer
camel.component.aws-s3.proxy-protocol To define a proxy protocol when instantiating the S3 client.   Protocol
camel.component.aws-s3.region The region in which S3 client needs to work. When using this parameter, the configuration will expect the capitalized name of the region (for example AP_EAST_1) You’ll need to use the name Regions.EU_WEST_1.name().   String
camel.component.aws-s3.secret-key Amazon AWS Secret Key.   String
camel.component.aws-s3.server-side-encryption Sets the server-side encryption algorithm when encrypting the object using AWS-managed keys. For example use AES256.   String
camel.component.aws-s3.storage-class The storage class to set in the com.amazonaws.services.s3.model.PutObjectRequest request.   String
camel.component.aws-s3.use-aws-k-m-s Define if KMS must be used or not. false Boolean
camel.component.aws-s3.use-encryption Define if encryption must be used or not. false Boolean
camel.component.aws-s3.use-i-a-m-credentials Set whether the S3 client should expect to load credentials on an EC2 instance or to expect static credentials to be passed in. false Boolean

[원문출처] http://camel.apache.org/defaulterrorhandler.html


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

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





DefaultErrorHandler

Camel 2.0 이후부터 새 기본 에러 핸들로 이다. .

 Dead Letter Channel처럼 같은 힘을 가지고 있다. 그러나 둘 사이의 단지 큰 차이점은 데드 레터 큐(dead letter queue)를 가지지 않는다

DefaultErrorHandler 는 Dead Letter Channel에서 환경 구성되었던 것과는 다르게 환경 구성 된다.:

  • 재 전송 없음
  • 처리 없음
  • 데드 레터 큐 (dead letter queue) 없음 (가능하지 않음)

기본적으로, 라우팅 되는 동안 던져진 어떤 exception 호출한 곳에 다시 전파되고 Exchange 는 바로 끝난다. 그러나, 처리된 표시함으로써 주어진 Exception 또는 더 낮은 Exception을 잡아내기 위해 Exception Clause 를 사용 할 수 있다 만약 호출한 곳에 돌려지지 않게 되면 Exchange 가 라우팅 되는 것을 계속 할 수 있다.

예제

아래 라우터에서, 안에 던져진 어떤 exception (예를 들면 validateOrder 빈) Jetty 엔드포인트를 통해서 다시 전파된다. 클라이언트에 HTTO 에러 메시지를 반환하게 될 것이다. 


from("jetty:http://localhost/myservice/order").to("bean:validateOrder").to("jms:queue:order");

이 경우에 다르게 확실한 Exception과 라우터를 잡아내기를 원하면 onException 을 추가 할 수 있다. 예를 들면 ValidationException을 잡아 내기 위해 호출한 곳에 고정된 응답을 반환 한다. d return a fixed response to the caller.


onException(ValidationException.class).handled(true).transform(body(constant("INVALID ORDER")));

 from("jetty:http://localhost/myservice/order").to("bean:validateOrder").to("jms:queue:order");

validateOrder 빈으로부터 ValidationException 이 발생했을 때, DefaultErrorHandler에 의해 인터셉터되고 onException(ValidationException.class)가 그 에러를 처리 하게 한다. 그래서 Exchange가 onException 라우터에 라우팅되고 handled(true) 를 사용할 때, 원본 Exception은 제거되고 고정된 응답 값으로 jetty 엔드포인트에 돌려줄 원래 호출한 곳에 반환될 메시지를 변형한다.

참고


[원문출처] http://camel.apache.org/dead-letter-channel.html


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

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




데드 레터 채널(Dead Letter Channel)

Camel은 Error Handler인 DeadLetterChannel를 사용하여 EIP patterns으로 부터 Dead Letter Channel을 지원한다.

데드 레터 채널 (Dead Letter Channel) 과 기본 에러 핸들러의 차이

기본 에러 핸들러는 매우 작다:  Exchange가 즉시 끝나고 호출한 곳에 던져진 Exception을 전달한다.

데드 레터 채널(Dead Letter Channel)은 재 전송을 포함하는 행위(호출한 곳에 던져진 Exception을 전파 할 것인지 여부, 실패 했을때 전달 해야 할 곳 등)을 조절 하는 것을 허용한다.

데드 레터 채널(Dead Letter Channel)은 또한 로그에서 verbose 모드가 아니게 환경 구성되어 있다. 그래서 메시지가 핸들링되고 데드 레터 엔드포인트에 옮겨 질 때 아무것도 로깅 되지 않는다. 만약 몇몇 로깅 레벨을 원하면 재전송 정책 / 환경 구성하기 위한 데드 레터 채털 상에 다양한 옵션을 사용할 수 있다. 예를 들면 만약 메시지 히스토리를 원하면 logExhaustedMessageHistory=true를 설정한다. (Camel 2.15.x 나 그 이후 버전은 logHandled=true로 설정한다. ).

DeadLetterChannel 이 데드 레터 엔드포인트에 메시지를 이동할 때 역시 기본적으로 데드 레터 채널에 의해 새로운 Exception이 핸들링 된다.  DeadLetterChannel이  항상 성공 하는 것을 보장한다. Camel 2.15 이후부터 이 행위는 deadLetterHandleNewException=false 옵션을 설정함으로써 변경 될 수 있다. 그래서 만약 새로운 Exception이 던져지게 될 때 데드 레터 채털(dead letter channel)은 실패하게 되고 기본 에러 핸들러의 행위인 새 Exception을 다시 돌려준다. (역주: 데드 레터 채널은 항상 성공이고 에러를 돌려주지 않으나 기본 에러 핸들러는 에러 발생시 바로 호출 한 곳으로 에러를 전파한다.). 새 Exception이 발생 했을 때 데드 레터 채널(dead letter channel) WARN 레벨로 로깅한다. logNewException=false를 설정함으로써 이 기능을 끌 수 있다..

재전송

임시 정전 또는 데이터베이스 데드락 때문에 메시지를 처리 하는데 실패 하는 원인이 되는 것이 일반적이다.그러나 만약 몇 초의 딜레이로 몇번  재시도 하면 완전히 좋게 될 것이다. 그래서 일반적으로 재전송을 시도하기 전에 얼마나 많이 메시지를 재 전송하기를 원하는지 그리고 얼마나 오래 기다릴 것인지 같은 몇몇 재 전송 정책을 사용하는 것을 원한다.

재 전송 정책(RedeliveryPolicy)은 재전송될 메시지를 어떻게 할 것인지 정의한다. 다음처럼 커스터마이징 할 수 있다.

  • 실패로 간주하고 데드 레터 채널로 보내기 전에 얼마나 많이 재 전송되는 것을 시도 하는가
  • 초기화 재 전송 타임아웃 
  • 지수 백오프 알고리즘을 사용하는지 아닌지 ( 예를 들면, 백오프 멀티플라이어를 사용하여 재시도 시간 간격 증가)
  • 충돌을 피하기 위해 타이밍에 약간의 랜덤을 추가할 것인지
  • 지연 패턴 (자세한 내용은 아래 참고)
  • Camel 2.11: 멈추는 중이거나 셧다운 중일 때 재 전송을 허용할 것인지 아닌지

메시지를를 재 전송하는 모든 시도가 실패하면 메시지는 데드 레터 큐(dead letter queue)로 보내진다.

Exchange가 데드 레터 큐(dead letter queue)에 옮겨지고 처리되는 방법

Dead Letter Channel 에서 처리

모든 재 전송 시도가 실패 했을때 Exchange 가 데드 레터 큐(dead letter queue: dead letter endpoint)로 이동된다. Exchange는 완료되고 뷰의 클라이언트 포인트로부터 처리되게 될 것이다.이와 같이Dead Letter Channel이 Exchange를 처리한다.

예를 들면 다음처럼 데드 레터 채널에 환경 구성한다. :

Fluent Builders를 사용


errorHandler(deadLetterChannel("jms:queue:dead").maximumRedeliveries(3).redeliveryDelay(5000));

Spring XML Extensions을 사용


<route errorHandlerRef="myDeadLetterErrorHandler">
   ...
</route>
 
<bean id="myDeadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
    <property name="deadLetterUri" value="jms:queue:dead"/>
    <property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/>
</bean>
 
<bean id="myRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
    <property name="maximumRedeliveries" value="3"/>
    <property name="redeliveryDelay" value="5000"/>
</bean>

위 Dead Letter ChannelExchange.EXCEPTION_CAUGHT 을 키값으로 하는 Exchange의 프로퍼티에 발생된 Exception을 옮김으로써 발생된 Exception(setException(null))을 클리어한다. 그러면 Exchange는 "jms:queue:dead" 에 옮겨지게 되고 클라이언트는 실패를 통보하지 않는다.

Exchange가 데드 레터 큐(dead letter queue)에 옮겨지고  원본 메시지를 사용하는 방법

useOriginalMessage 옵션이 라우팅 하는 동안 잠재적으로 수정된 현재의 메시지 대신에 원본 입력 메시지를 라우팅 하기 위해 사용된다.

예를 들면 다음 라우터를 사용하면 :


from("jms:queue:order:input")
    .to("bean:validateOrder")
    .to("bean:transformOrder")
    .to("bean:handleOrder");

이 라우터는 JMS 메시지를 리스닝하고 검증하고 변형하고 처리 한다. 이 Exchange 페이로드가 변형되고 변경되는 동안 이 경우 무언가 잘못되었기 때문에 다른 JMS destination으로 메시지를 옮기기를 원한다. 그러면 우리는 useOriginalMessage 옵션으로 Dead Letter Channel 에 환경 구성할 수 있다.  그러나 destination에 Exchange 가 옮겨졌을 때 이 안에 있는 메시지의 상태를 우리는 알지 못한다. transformOrder 이전에 또는 이후에 에러가 발생했는가? 그래서 jms:queue:order:input 로부터 받은 원본 입력 메시지를 옮기는 것을 원하는지 확인 해야 한다. 그래서 아래처럼 useOriginalMessage 옵션을 활성화함으로써 가능하다.:


// will use original body
errorHandler(deadLetterChannel("jms:queue:dead")
   .useOriginalMessage().maximumRedeliveries(5).redeliverDelay(5000);

그러면 jms:queue:dead에 라우팅된 메시지는 원본 입력 값이다. 만약 수동으로 재 시도 하는 것을 원하면 Input 큐에 JMS 메시지를 옮길 수 있다. 메시지가 아무런 문제가 없다면 메시지는 우리가 수신 받은 원본과 같다.

OnRedelivery

Dead Letter Channel이 재 전송 중 일 때, 매번 재 전송을 시도하기 전에 실행되는 Processor를 환경 구성 하는 것이 가능하다. 재전송 되기 전에 메시지를 바꿀 필요가 있는 상황에서 사용 될 수 있다. 아래 다음 예제를 보라..

onException 과 onRedeliver

onException 당 onRedeliver를 설정하는 것을 지원한다. 이 말의 의미는 다른 Exception을 위해 특정 재 전송을 할 수 있다는 것이다. 반대로 Dead Letter Channel에 onRedelivery 를 설정하는 것은 위해 글로벌 스코프처럼 보여 질 수 있다.

재전송 기본 값 (Redelivery default values)

기본적으로 재 전송은 비활성화 되어 있다.

기본 재 전송 정책은 다음 값을 사용 하게 될 것이다. :

  • maximumRedeliveries=0
  • redeliverDelay=1000L (1 초)
  • maximumRedeliveryDelay = 60 * 1000L (60 초)
  • 그리고 지수 백오프 알고리즘과 충돌 방지가 꺼져있다.
  • retriesExhaustedLogLevel이 LoggingLevel.ERROR로 설정되어 있다.
  • retryAttemptedLogLevel이 LoggingLevel.DEBUG로 설정되어 있다.
  • Stack traces 가 Camel 2.2 이후부터 소모된 메시지를 위해 로깅된다.
  • Camel 2.3 이후 부터 처리된 exception들은 로딩되지 않는다. 
  • 기본 에러 핸들러를 위해 logExhaustedMessageHistory가 true이다. 그리고 데드 레터 채널(dead letter channel)을 위해 false 이다.
  • Camel 2.17: logExhaustedMessageBody은 기본적으로 민감한 메시지의 Body와 Header 상세 로깅을 피하기 위해  비활성화 되어 있다.만약 이 옵션이 true이면, logExhaustedMessageHistory 옵션도 true여야만 한다..

최대 재 전송 지연 시간은 그 값 보다 지연시간이 더 길지 않다는 것을 보장한다.  기본값 1분. 지수 오프백 알고리즘이 켜져 있다면 발생 할 수 있다.

최대 재 전송은 재 전송을 시도할  수 이다. 기본적으로 Camel은 Exchange 1 + 5회를 처리 하기 위해 시도한다. 일반 시도 1회, 재전송으로 5회 시도한다. 
maximumRedeliveries에 -1과 같은 음수를 설정하면 항상 재 전송한다. (제한 없음).
maximumRedeliveries에 0을 설정하면 어떠한 재 전송 시도도 비활성화 된다.

Camel은 기본적으로 DEBUG 레벨에 전송 실패를 로깅하게 될 것이다. retriesExhaustedLogLevel 또는 를 지정함으로써 변경 할 수 있다. 예지는 ExceptionBuilderWithRetryLoggingLevelSetTest 를 보라 

stack traces의 로깅을 켜고 끌수 있고 만약 꺼져있다면 Camel은 여전히 재 전송 시도를 로깅 하게 될 것이다. 단지 많이 덜 자세한 로그이다.

재 전송 지연 패턴 

지연 패턴은 지연을 위한 범위 패턴을 설정하기 위한 단일 옵션처럼 사용된다. 만약 사용되면 다음 옵션(delay, backOffMultiplier, useExponentialBackOff, useCollisionAvoidance, maximumRedeliveryDelay)은 적용되지 않는다.

다음 구문을 사용하여 범위의 그룹을 설정한다. : limit:delay;limit 2:delay 2;limit 3:delay 3;...;limit N:delay N

각각의 그룹은 콜론으로 구분된 두 값을 가진다.

  • limit = 상위 제한 limit
  • delay = 밀리세컨드 지연시간
    그리고 그룹은 다시 세비 콜론으로 구분된다.
    다음 그룹이 이전 그룹보다 더 높은 제한을 가져야 하는 것은 경험 법칙이다.

다음 예로 명확하게 해보자:
delayPattern=5:1000;10:5000;20:20000

3개 그룹들이 주어졌다.:

  • 5:1000
  • 10:5000
  • 20:20000

재 전송 시도를 위한 3개의 지연시간의 결과:

  • 재 전송 시도 1..4회차 = 0 millis (첫번째 그룹이 5부터 시작 하므로)
  • 재 전송 시도 5..9회차 = 1000 millis (첫번째 그룹)
  • 재 전송 시도 10..19회차 = 5000 millis (두번째 그룹)
  • 재 전송 시도 20..회차 이상 = 20000 millis (마지막 그룹)

주의 : 첫번째 재 전송 시도는 1 이다 첫번째 그룹은 1부터 시작하거나 더 커야 한다. 

제한이 1부터 시작하는 그룹으로 지연 시간이 시작 될 수 있다. : delayPattern=1:1000;5:5000

  • 재 전송 시도 1..4회차 = 1000 millis (첫번째 그룹)
  • 재 전송 시도 5..회차 이상 = 5000 millis (마지막 그룹)

다음 지연시간이 이전 보다 높아야 할 필요는 없다. 원하는 지연 시간 값을 사용할 수있다. 예를 들면  delayPattern=1:5000;3:1000, 5초 단위로 지연 시간을 가지고 시작해서 마지막에는 1초 단위로 감소한다. 

재 전송 헤더 (Redelivery header)

메시지가 재 전송 될 때, DeadLetterChannel은 얼마나 많은 재 전송 시도를 하였는지 표시하기 위해 메시지에 사용자 정의 헤더를 추가 한다. 
Camel 2.6 이전 버전: 헤더는 Exchange.REDELIVERY_COUNTER에 정의된 CamelRedeliveryCounter이다.

Camel 2.6 이후 부터: 헤더는 최대 전송을 설정 하는 것을 포함하는 Exchange.REDELIVERY_MAX_COUNTER에 정의된 CamelRedeliveryMaxCounter이다. 만약 retryWhile 을 사용하거나 또는 환경 구성된 최대 재 전송에 제한이 없으면 이 헤더 값은 존재 하지 않는다. 

그리고 불린 값으로 재 전송 될지 아닌지를 판단. (첫번째 시도에서)
헤더 값 CamelRedelivered은 불린 값으 포함한다. 만약 재 전송 되거나 아니거나 이면 Exchange.REDELIVERED 에 정의 되어 있다. 

exchange로 부터 동적으로 계산된 지연 시간.
Camel 2.9 또는 2.8.2에서 : 헤더 값 CamelRedeliveryDelayExchange.REDELIVERY_DELAY에 정의 되어 있고 이 헤더 값이 없으면 일반 재 전송 률이 적용된다..

어느 엔드포인트가 실패인가?

Camel 2.1부터 가능 한 것

Camel이 메시지를 라우터 할 때 마지막 엔드포인트를 포함하는 속성을 가진 Exchange 장식한다. Camel은 Exchange 를 보낸다. :


String lastEndpointUri = exchange.getProperty(Exchange.TO_ENDPOINT, String.class);

Exchange.TO_ENDPOINT 는 CamelToEndpoint 상수 값을 가진다. .

이 정보는 Camel이 어떤 엔드 포인트에 메시지를 보낼때 업데이트 된다. 그래서 만약 존재 하면 카멜이 Exchange를 보낸 마지막 엔드 포인트 이다. 

예를 들면 주어진 Endpoint 에 Exchange를 처리하거나 그 메시지가 데드 레터 큐(dead letter queue)로 옮겨 질 때  Camel은 또한 마지막 엔드포인트를 포함하는 또 다른 프로퍼티를 Exchange를 장식한다.:


String failedEndpointUri = exchange.getProperty(Exchange.FAILURE_ENDPOINT, String.class);

Exchange.FAILURE_ENDPOINT 는 CamelFailureEndpoint 상수 값을 가진다..

예를 들면 데드 레터 큐(dead letter queue)에 정보를 패치하고 에러 리포팅을 위해 사용하는 것을 허용한다. 

만약 Camel 라우터가 동적 Recipient List  같은 동적 비트이면 실패한 엔드포인트를 알 수 있다.

주의: 그 정보들은 주어진 엔드포인트에 의해 심지어 메시지가 성공적으로 처리되더라도  Exchange에 유지된다. 그리고 예를 들면 로컬 Bean 에서 마지막 실패는 대신 처리 된다.  그래서 정확한 에러를 돕는 힌트를 조심해야 한다. 

from("activemq:queue:foo")
    .to("http://someserver/somepath")
    .beanRef("foo");

이제 위 라우터가 foo 빈에서 실패가 발생하는 것을 가정한다. 그러면 Exchange.TO_ENDPOINT 와 Exchange.FAILURE_ENDPOINT가 여전히 http://someserver/somepath 값을 포함하게 될 것이다 .

OnPrepareFailure

Camel 2.16부터 가능

exchange가 데드 레터 큐(dead letter queue)에 보내지기 전에, you can use onPrepare to allow a custom Processor to prepare the exchange를 준비하기 위해 Exchange가 왜 실패 했는지 정보를 추가 하는 것 같은 사용자 정의 Processor 를 허용하기 위해  onPrepare 를 사용 할 수 있다.  예를 들면 다음 프로세서는 Exception 메시지를 헤더에 추가한다.

public static class MyPrepareProcessor implements Processor {
    @Override
    public void process(Exchange exchange) throws Exception {
        Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
        exchange.getIn().setHeader("FailedBecause", cause.getMessage());
    }
}

그리고 다음처럼 프로세서를 사용하기 위해 에러 핸들러를 환경 구성한다. :


errorHandler(deadLetterChannel("jms:dead").onPrepareFailure(new MyPrepareProcessor()));

 

XML DSL으로 환경 구성하는 것은 다음 보여지는 것과 같다. :

<bean id="myPrepare"
      class="org.apache.camel.processor.DeadLetterChannelOnPrepareTest.MyPrepareProcessor"/>
 
 
  <errorHandler id="dlc" type="DeadLetterChannel" deadLetterUri="jms:dead" onPrepareFailureRef="myPrepare"/>

 

The onPrepare is also available using the default error handler.

Which route failed

Available as of Camel 2.10.4/2.11

When Camel error handler handles an error such as Dead Letter Channel or using Exception Clause with handled=true, then Camel will decorate
the Exchange with the route id where the error occurred.

String failedRouteId = exchange.getProperty(Exchange.FAILURE_ROUTE_ID, String.class);

The Exchange.FAILURE_ROUTE_ID have the constant value CamelFailureRouteId.

This allows for example you to fetch this information in your dead letter queue and use that for error reporting.

stopping/shutdown 되는 동안 재 전송이 허용될 때 컨트롤

Camel 2.11이후부터 가능

Camel 2.10 이전은, Camel 라우터가 멈추거나 Camel이 셧다운 되는 동안 재 전송을 수행하게 될 것이다. 이것이 Camel 2.10는 적극적으로 셧다운되는동안은 재 전송 시도를 수행하지 않는 것 처럼 조금 개선 되었다. (예를 들면 Graceful Shutdown 동안 그리고 타임아웃을 입력하면). Camel 2.11 이후부터 재 전송을 허용하는지 아닌지 컨트롤 하기 위해 사용할 수 있는 새 옵션 allowRedeliveryWhileStopping이 있다.; 어진행중엔 어떠한 재 전송도 여전히 실행 되는 것에 주의하라 이 옵션은 단지 route가 멈추는 중이거나 / Camel이 shutdown이 실행된 이후에  어떤 재 전송이 실행되는 것은 허용하지 않는다. 만약 재 전송이 허용되지 않는다면, Exchange 에 RejectedExcutionException 설정 될 것이고  Exchange 정지 처리를 한다. 그 의미는 모든 Comsumer는 RejectedExecutionException 실패로 Exchange 를 보게 될 것이다.   

역주) Route가 정지되거나 Camel이 셧다운되면 진행중인 프로세스는 모드 Exchange RejectedExcutionException 으로 오류 처리 한 후에 정지 및 셧다운이 수행된다.

이전 처럼 이전 버전과 호환 가능하게 되는 것은 기본 값은 true이다 to be backwards compatible as before. 예를 들면 다음 예제는 어떻게  Java DSL 과 XML DSL를 사용 하는지를 방법을 보여 준다.

// this error handler will try up till 20 redelivery attempts with 1 second between.
// however if we are stopping then do not allow any redeliver attempts.
errorHandler(defaultErrorHandler()
        .allowRedeliveryWhileStopping(false)
        .maximumRedeliveries(20).redeliveryDelay(1000).retryAttemptedLogLevel(LoggingLevel.INFO));
 
from("seda:foo").routeId("foo")
    .to("mock:foo")
    .throwException(new IllegalArgumentException("Forced"));

그리고 XML DSL로  사용하는 샘플

<!-- notice we use the errorHandlerRef attribute to refer to the error handler to use as default -->
   <camelContext errorHandlerRef="myErrorHandler" xmlns="http://camel.apache.org/schema/spring">
 
    <!-- configure error handler, to redeliver up till 10 times, with 1 sec delay
         and if we are stopping then do not allow redeliveries, to stop faster -->
    <errorHandler id="myErrorHandler" type="DefaultErrorHandler">
        <redeliveryPolicy maximumRedeliveries="20" redeliveryDelay="1000" allowRedeliveryWhileStopping="false" retryAttemptedLogLevel="INFO"/>
    </errorHandler>
 
       <route id="foo">
           <from uri="seda:foo"/>
        <to uri="mock:foo"/>
        <throwException ref="forced"/>
       </route>
 
   </camelContext>

샘플

다음 예제는 DSL을 사용하여 Dead Letter Channel을  어떻게 환경 구성하는지를 보여 준다. 

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // using dead letter channel with a seda queue for errors
        errorHandler(deadLetterChannel("seda:errors"));
 
        // here is our route
        from("seda:a").to("seda:b");
    }
};

이 예제로 RedeliveryPolicy을 환경 구성할 수 있다.

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // configures dead letter channel to use seda queue for errors and use at most 2 redelveries
        // and exponential backoff
        errorHandler(deadLetterChannel("seda:errors").maximumRedeliveries(2).useExponentialBackOff());
 
        // here is our route
        from("seda:a").to("seda:b");
    }
};

어떻게 재 전송 전에 Exchange 를 변경 할 수 있는가?

Dead Letter Channel 에서 직접적으로 각각의 재 전송 시도 이전에 수행되어야 할 Processor 를 설정 하는 것을 지원한다. 

Dead Letter Channel이 재 전송이 수행 될 때, 모든 재 전송 시도 이전에 단지 실행할 Processor 를 환경 구성하는 것이 가능하다. 재 전송 이전에 메시지를 변경할 필요가 있을 때 어느 상황에서나 사용 될 수 있다. 

여기 각각의 재 전송 이전에 수행될 MyRedeliveryProcessor 를 사용하기 위해 Dead Letter Channel을 환경 구성한다.

// we configure our Dead Letter Channel to invoke
// MyRedeliveryProcessor before a redelivery is
// attempted. This allows us to alter the message before
errorHandler(deadLetterChannel("mock:error").maximumRedeliveries(5)
        .onRedelivery(new MyRedeliverProcessor())
        // setting delay to zero is just to make unit testing faster
        .redeliveryDelay(0L));

그리고 메시지를 변경할 곳에서 MyRedeliveryProcessor 이다..

// This is our processor that is executed before every redelivery attempt
// here we can do what we want in the java code, such as altering the message
public class MyRedeliverProcessor implements Processor {
 
    public void process(Exchange exchange) throws Exception {
        // the message is being redelivered so we can alter it
 
        // we just append the redelivery counter to the body
        // you can of course do all kind of stuff instead
        String body = exchange.getIn().getBody(String.class);
        int count = exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER, Integer.class);
 
        exchange.getIn().setBody(body + count);
 
        // the maximum redelivery was set to 5
        int max = exchange.getIn().getHeader(Exchange.REDELIVERY_MAX_COUNTER, Integer.class);
        assertEquals(5, max);
    }
}

무슨 이유로 데드 레터 채널이 호출 되었는지 어떻게  로그 기록 할 수 있나 ?

종종 무엇이 잘못되어 데드 레터 채널이 발생되어 갔었는지 알 필요가 있다. 그러나 이 목적을 로깅 하는 것을 제공하지는 않는다. 그래서 Dead Letter Channel의 엔드포인트는 자신의 엔드 포인트에 설정 될 필요가 있다. (direct:deadLetterChannel 처럼). 우리는 실패한 Exchange 를 옮기기를 원하는 곳 앞에 Exchange 를 받아 들이고 Exception을 로그 기록하기 위해 라우터를 작성한다. (예를 들면 DLQ 큐라 할지라도).  http://stackoverflow.com/questions/13711462/logging-camel-exceptions-and-sending-to-the-dead-letter-channel를 보라

이패턴 사용하기 

만약 EIP 패턴을 사용하는 것을 원하면 Getting Started를 읽어라. 아마 특별히 Endpoint 와 URIs 상세한 묘사하는 유용한 아키텍처를 찾을 수 있을 것이다.  그러면 당신은 패턴을 찾는 것을 시도하기 전에 이 예제(Examples )를 시도할 수 있습니다. 




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


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

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




에러 핸들러(Error Handler)

Camel은 이벤트 기반 Consumer가 에러 처리하는 것을 다루기 위해 플러그인 가능한 ErrorHandler 전략들을 제공한다. 예외 절(Exception Clause)를 사용하여 DSL에서 직접 에러 핸들링을 지정하는 것은 선택적이다.  

소개와 배경 지식를 위해  Error handling in Camel 을 보라.

예외 절(Exception Clause)

Error Handler 가 Exception Clause을 결합하여 사용하는 것은 매우 파워풀한 결합이다. 최종사용자(end-users)들이 에러를 핸들링하는 전략에서 이것을 조합하는 것을 권장한다. 샘플과 Exception Clause를 보라.

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

라우터에서 직접 사용할 수 있는 DSL 처럼 에러 핸들링과 관련된 것이 Try Catch Finally 이다. 기본적으로 자바에서 try catch finally 를 모방이지만 더 파워풀하다.

현재 Camle 구현체들이 다음 특별한 기능을 제공한다. :

비 트랜잭션 (Non transacted : 트랜잭션을 지원하지 않는)

  • DefaultErrorHandler 는 Camel 에서 기본 에러 핸들러이다. 이 에러 핸들러는 데드 레터 큐(dead letter queue)를 지원하지 않고 호출한 곳에 exception을 전달하게 될 것이다. 만약 전혀 에러 핸들러가 없다면 Features의 설정에 제한을 가진다.
  • Dead Letter Channel 는 데드 레터 엔드포인트에 보내기 전에 메시지 교환의 횟수를 재 전송하기 위해 시도하는 것을 지원한다.
  • LoggingErrorHandler는 단지 Exception을 잡아내고 로깅하기 위한 것이다.
  • NoErrorHandler 는 어떠한 에러 핸들링도 없는 것이다.

트랜잭션 (Transacted : 트랜잭션을 지원하는)

에러 핸들러들은 다음 예에서 보여주는 것처럼 DSL에서 룰 전체 또는 특정 라우팅 룰에 지원 될 수 있다. 에러 핸들러 룰들은 단일 RouteBuilder 안에서 각각 라우팅하는 룰 위에 상속 된다. 

제공되는 에러 핸들러의 간단한 요약

DefaultErrorHandler

DefaultErrorHandler 는 Camel 에서 기본에러 핸들러이다. Dead Letter Channel 와 다르게 어떠한 데드 레터 큐(dead letter queue)를 가지고 있지 않다. 그리고 기본적으로 Exception들을 핸들링 하지 않는다.

Dead Letter Channel

Dead Letter Channel은 1초 딜레이를 사용하여 최대 6번의 재 전송을 할 것이다. 만약 exchange가 실패 하면 ERROR 레벨에 로깅 될 것이다.

사용하기 위해 기본 데드 레터 엔드포인트를 환경 설정 할 수 있다. :

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // using dead letter channel with a seda queue for errors
        errorHandler(deadLetterChannel("seda:errors"));
 
        // here is our route
        from("seda:a").to("seda:b");
    }
};

또는 in Spring DSL 에서

<bean id="deadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
  <property name="deadLetterUri" value="log:dead"/>
</bean>
 
<camelContext errorHandlerRef="deadLetterErrorHandler" xmlns="http://camel.apache.org/schema/spring">
  ...
</camelContext>

또는 Camel 2.3.0 이후 부터 또한

<camel:errorHandler id="deadLetterErrorHandler" type="DeadLetterChannel" deadLetterUri="log:dead">
 
<camel:camelContext errorHandlerRef="deadLetterErrorHandler">
  ...
</camel:camelContext>

Logging Error Handler

로깅 에러 핸들러는 캐치되지 않은 Exception이 던져 질 때 마다 기본적으로 ERROR 레벨에 로깅 될 것이다. 로깅 카테고리, 로거, 레벨은 빌더에서 모두 정의 될 수 있다.


errorHandler(loggingErrorHandler("mylogger.name").level(LoggingLevel.INFO));

또는 Spring DSL 에서

<bean id="loggingErrorHandler" class="org.apache.camel.builder.LoggingErrorHandler">
  <property name="logName" value="mylogger.name"/>
  <property name="level" value="DEBUG"/>
</bean>
 
<camelContext errorHandlerRef="loggingErrorHandler" xmlns="http://camel.apache.org/schema/spring">
  ...
</camelContext>

또는 Camel 2.3.0 이후 부터 또한

<camel:errorHandler id="loggingErrorHandler" type="LoggingErrorHandler" logName="mylogger.name" level="DEBUG"/>
 
<camel:camelContext errorHandlerRef="loggingErrorHandler">
  ...
</camel:camelContext>

이것은 카테고리는 mylogger.name 을 사용하여 에러 핸들러를 생성하게 되고 그리고 모든 로그 메시지를 생성하기 위해 INFO 레벨을 사용한다.


from("seda:a").errorHandler(loggingErrorHandler("mylogger.name").level(LoggingLevel.DEBUG)).to("seda:b");

또 로거는 특정 라우터를 위해서 정의 될 수 있다. may also be defined for specific routes.

No Error Handler

no error handler는 에러 핸들링을 비활성화 하기 위해 사용된다.


errorHandler(noErrorHandler());

또는 Spring DSL에서

<bean id="noErrorHandler" class="org.apache.camel.builder.NoErrorHandlerBuilder"/>
 
<camelContext errorHandlerRef="noErrorHandler" xmlns="http://camel.apache.org/schema/spring">
  ...
</camelContext>

또는 Camel 2.3.0 이후 부터 또한

<camel:errorHandler id="noErrorHandler" type="NoErrorHandler"/>
 
<camel:camelContext errorHandlerRef="noErrorHandler">
  ...
</camel:camelContext>

TransactionErrorHandler

TransactionErrorHandler는 Camel에서 트랜잭션이 적용된 라우터를 위한 기본 에러 헨들러이다. 

만약 트랜잭션을 지원하는 DSL을 사용하여 트랜잭션으로 라우터를 만들면 Camel은 자동적으로 TransactionErrorHandler를 사용하게 될 것이다. 글로벌 또는 라우터당 환경 구성된 에러 핸들러를 찾으려고 시도하게 될 것이고 만약 TransactionErrorHandlerBuilder 인스턴스이면 그걸 사용하게 될 것이다. 만약 Camel에서 찾지 못하면 기본 에러 핸들러를 우선하는 임시 TransactionErrorHandler가 자동으로 생성되게 될 것이다. 환경 구성을 통한 규칙이다.

다양한 Error Handlers의 기능들을 지원한다.

Error Handler(들)에 의해 지원되는 기능이 여기 있다. :

위 기능들의 일부의 문서는 Exception 절(Exception Clause) 문서를 보라.

Scopes

에러 핸들러의 스코프는 다음 중 하나 이다.

  • global
  • route 당

다음 예는 어떻게 글로벌 에러 핸들러를 등록하는지를 보여준다. (이 경우에서는 logging handler를 사용한다.)

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // logging error handler를 사용
        errorHandler(loggingErrorHandler("com.mycompany.foo"));
 
        // 여기서 표준 라우터이다.
        from("seda:a").to("seda:b");
    }
};

다음 예는 어떻게 라우터에 특정 에러 핸들러를 등록할 수 있는지를 보여 준다. 커스터마이징 된 로그 핸들러는 단지 Endpoint seda:a로 부터 라우터를 위해서 등록된다. 

RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        // 이 라우터는 중첩된 로깅 에러 핸들러를 사용하고 있다.
        from("seda:a")
            // 여기에 logging error handler를 환경 구성한다..
            .errorHandler(loggingErrorHandler("com.mycompany.foo"))
            // 그리고 여기로 라우팅을 계속 한다.
            .to("seda:b");
 
        // 이 라우터는 기본 에러 핸들러 (DeadLetterChannel)을 사용하게 될 것이다.
        from("seda:b").to("seda:c");
    }
};

Spring 기반의 환경 구성

Java DSL 대 Spring DSL

에러 핸들러는 Java DSL과 Spring DSL 에서 크게 다르게 환경 설정 된다. Jaba DSL은 능숙한 빌더를 사용하는 반면에 Spring DSL은 표준 Spring Bean 환경에 더 의존한다.

에러 핸들러는 스프링 빈과 다음 스코프 에서 처럼 환경 구성 될 수 있다. :

  • global (camelContext 테그)
  • route 당 (route 테그)
  • policy 당 (policy/transacted 테그)

에러 핸들러는 errorHandlerRef 속성으로 환경 구성 될 수 있다.

에러 핸들러 계층(Error Handler Hierarchy)

에러 핸들러는 상속 된다. 그래서 만약 당신이 글로벌 에러 핸들러를 설정하면 어디서든지 사용 가능하다. 그러나 라우터에서 또는 다른 에러 핸들러를 사용하여 오버라이딩 할 수 있다. 

Spring 기반 환경 구성 예제

이 예에서 라우터에서 최종 3번과 재시도 전에 약간의 딜레이로 재전송하는 라우터에서 Dead Letter Channel 을 환경 구성한다.

먼저 route 테그에서 errorHandlerRef 속성을 사용하여 myDeadLetterErrorHandler 에 참조를 환경 설정한다..

  <camelContext xmlns="http://camel.apache.org/schema/spring">
      <template id="myTemplate"/>
<!-- DeadLetterChannel에 errorHandlerRef 를 설정, 단지 이 라우터를 위해서만 적용된다. -->
      <route errorHandlerRef="myDeadLetterErrorHandler">
          <from uri="direct:in"/>
          <process ref="myFailureProcessor"/>
          <to uri="mock:result"/>
      </route>
  </camelContext>

그리고 Dead Letter Channel인 스프링 bean 엘리먼트를 사용하여 표준 스프링으로  myDeadLetterErrorHandler를 환경 구성한다.

그리고 마지막으로 얼마나 많이 재전송할 것인지 지연시킬 것인지 등을 위한 옵션을 환경 구성할 재전송 정책을 위한 다른 Spring 빈을 가진다.

<!-- 여기 DeadLetterChannel을 환경 구성한다. -->
<bean id="myDeadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
     <!-- 재 전송 실패 시 exchange가 mock:dead 에 라우팅 된다. -->
       <property name="deadLetterUri" value="mock:dead"/>
     <!-- 사용할 재전송 정책을 참조한다. -->
       <property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/>
</bean>
 
   <!-- 여기 재 전송 설정을 설정한다. -->
<bean id="myRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
     <!-- 최대 3번 재전송 시도하고 전송 실패 시 mock:dead endpoint에 라우팅 된다. -->
       <property name="maximumRedeliveries" value="3"/>
     <!-- 재전송 전에 delay 250ms초 지연 -->
       <property name="redeliveryDelay" value="250"/>
</bean>

Camel 2.3.0 부터, Camel은 에러 핸들러를 위하여 customer 빈 환경 구성을 제공한다.  여기 예제가 있다.

<errorHandler id="loggingErrorHandler" type="LoggingErrorHandler" logName="foo" level="INFO"
 
<!-- 만약 유형 속성이 지정되지 않으면 유형 값은 DefaultErrorHandler가 설정되게 될 것이다. -->
<errorHandler id="errorHandler" xmlns="http://camel.apache.org/schema/spring"/>
 
<!-- 에러 핸들러 안쪽에 재전송 정책(redeliveryPolicy )을 정의 할 수 있다. -->
<camel:errorHandler id="defaultErrorHandler" type="DefaultErrorHandler">
    <camel:redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="0" logStackTrace="false"/>
</camel:errorHandler>
 
<camel:errorHandler id="deadLetterErrorHandler" type="DeadLetterChannel" deadLetterUri="log:dead">
    <camel:redeliveryPolicy maximumRedeliveries="2" 
redeliveryDelay="1000" 
logHandled="true" 
asyncDelayedRedelivery="true"/>
</camel:errorHandler>
 
<bean id="myErrorProcessor" class="org.apache.camel.spring.handler.MyErrorProcessor"/>
 
<!-- TX 에러 핸들러는 템플릿을 사용하여 환경 구성 될 수 있다. -->
<camel:errorHandler id="transactionErrorHandler" type="TransactionErrorHandler"
                    transactionTemplateRef="PROPAGATION_REQUIRED" onRedeliveryRef="myErrorProcessor"/>
 
<!-- 또는 트랜잭션 관리 를 사용한다. -->
<camel:errorHandler id="txEH" type="TransactionErrorHandler" transactionManagerRef="txManager"/>
 
<!-- camelContext 안쪽에 에러 핸들러를 정의 할 수 있다. -->
<camelContext errorHandlerRef="noErrorHandler" xmlns="http://camel.apache.org/schema/spring">
    <errorHandler id="noErrorHandler" type="NoErrorHandler"/>
</camelContext>

트랜잭션을 지원하는(transactional) 에러 핸들러 사용

트랜잭션 에러 핸들러는 스프링 트랜잭션을 기반으로 되어 있고 camel-spring component의 사용을 필요로 한다..
사용하는 방법과 에러 핸들러로 환경 구성하는 트랜잭션 행위와 환경 구성을 위한 많은 예가 있는 Transactional Client를 보라.

See also


[원문출처] 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