1. 개요
이 사용방법(예제)에서는 시스템을 통해 흐르는 메시지를 모니터링하는 데 도움이 되는 Wire Tap Enterprise Integration Pattern(EIP)에 대해 설명합니다 .
이 패턴을 사용하면 메시지를 채널에서 영구적으로 소비하지 않고 메시지를 가로챌 수 있습니다 .
2. 와이어 탭 패턴
Wire Tap은 지점간 채널을 통해 이동하는 메시지를 검사합니다 . 메시지를 수신하고 사본을 만들어 Tap Destination으로 보냅니다 .
이를 더 잘 이해하기 위해 ActiveMQ 및 Camel을 사용하여 Spring Boot 애플리케이션을 생성해 보겠습니다 .
3. 메이븐 의존성
camel-spring-boot-dependencies를 추가해봅시다 .
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-dependencies</artifactId>
<version>${camel.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
이제 camel-spring-boot-starter를 추가합니다 .
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
경로를 통해 흐르는 메시지를 보려면 ActiveMQ 도 포함해야 합니다 .
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-activemq-starter</artifactId>
</dependency>
4. 메시징 교환
메시지 객체를 만들어 봅시다:
public class MyPayload implements Serializable {
private String value;
...
}
이 메시지를 direct:source 로 전송하여 경로를 시작합니다.
try (CamelContext context = new DefaultCamelContext()) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
connectionFactory.setTrustAllPackages(true);
context.addComponent("direct", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
addRoute(context);
try (ProducerTemplate template = context.createProducerTemplate()) {
context.start();
MyPayload payload = new MyPayload("One");
template.sendBody("direct:source", payload);
Thread.sleep(10000);
} finally {
context.stop();
}
}
다음으로 경로를 추가하고 목적지를 탭합니다.
5. 교환 탭하기
wireTap 메서드 를 사용하여 탭 대상의 Endpoints URI를 설정합니다 . Camel은 메시지 교환 패턴을 InOnly 로 설정하기 때문에 wireTap 의 응답을 기다리지 않습니다 . Wire Tap 프로세서는 별도의 스레드 에서 이를 처리합니다 .
wireTap("direct:tap").delay(1000)
낙타의 와이어 탭 노드는 교환을 탭할 때 두 가지 맛을 지원합니다.
5.1. 전통적인 와이어 탭
기존 Wire Tap 경로를 추가해 보겠습니다.
RoutesBuilder traditionalWireTapRoute() {
return new RouteBuilder() {
public void configure() {
from("direct:source").wireTap("direct:tap")
.delay(1000)
.bean(MyBean.class, "addTwo")
.to("direct:destination");
from("direct:tap").log("Tap Wire route: received");
from("direct:destination").log("Output at destination: '${body}'");
}
};
}
여기에서 Camel은 Exchange 만 복사 합니다 . 심층 복제는 수행하지 않습니다 . 모든 복사본은 원본 교환의 개체를 공유할 수 있습니다.
여러 메시지를 동시에 처리하는 동안 최종 페이로드가 손상될 가능성이 있습니다 . 이를 방지하기 위해 페이로드를 탭 대상으로 전달하기 전에 페이로드의 딥 클론을 생성할 수 있습니다.
5.2. 새 교환 보내기
Wire Tap EIP는 Exchange 사본으로 미리 채워진 Expression 또는 Processor를 지원 합니다 . 식은 메시지 본문을 설정하는 데만 사용할 수 있습니다 .
프로세서 변형 은 교환이 채워지는 방식(설정 속성, 헤더 등)에 대해 완전한 권한을 부여합니다.
페이로드에서 딥 클로닝을 구현해 보겠습니다 .
public class MyPayload implements Serializable {
private String value;
...
public MyPayload deepClone() {
MyPayload myPayload = new MyPayload(value);
return myPayload;
}
}
이제 원래 교환의 복사본을 입력으로 사용하여 Processor 클래스를 구현해 보겠습니다.
public class MyPayloadClonePrepare implements Processor {
public void process(Exchange exchange) throws Exception {
MyPayload myPayload = exchange.getIn().getBody(MyPayload.class);
exchange.getIn().setBody(myPayload.deepClone());
exchange.getIn().setHeader("date", new Date());
}
}
wireTap 직후에 onPrepare를 사용하여 호출합니다 .
RoutesBuilder newExchangeRoute() throws Exception {
return new RouteBuilder() {
public void configure() throws Exception {
from("direct:source").wireTap("direct:tap")
.onPrepare(new MyPayloadClonePrepare())
.end()
.delay(1000);
from("direct:tap").bean(MyBean.class, "addThree");
}
};
}
6. 결론
이 기사에서는 특정 메시지 Endpoints을 통과하는 메시지를 모니터링하기 위해 Wire Tap 패턴을 구현했습니다. Apache Camel의 wireTap을 사용하여 메시지를 복사하고 기존 흐름을 변경하지 않고 다른 Endpoints으로 보냅니다.
Camel은 교환을 탭하는 두 가지 방법을 지원합니다. 전통적인 Wire Tap에서는 원본 교환이 복사됩니다. 두 번째로 새로운 거래소를 만들 수 있습니다. Expression 을 사용하여 메시지 본문의 새 값으로 이 새로운 교환을 채우 거나 Processor 를 사용하여 헤더와 선택적으로 본문을 설정할 수 있습니다 .
코드 샘플은 GitHub에서 사용할 수 있습니다 .