2017-09-25 15 views
0

소비자가 실패 할 때 JMS 메시지의 재전송을 보장해야하지만 여기에서 비슷한 질문에 허용되는 전략이 내 케이스에 적용되지 않을 수 있습니다.클라이언트가 충돌했을 때 JMS 메시지 재전송을 보장하는 방법

JMS 클라이언트 - 스프링 + activeMq - 손실되거나 복제 될 수없는 메시지를받는 경우를 고려하십시오. 메시지 처리에 비용이 많이 들기 때문에 클라이언트는이를 일괄 적으로 처리합니다. 이 시나리오는 다음과 같이한다 :

  • T1이 - 클라이언트가받는 메시지 A, B, C 및 D
  • T2 - 스레드는 클라이언트에서 깨어 메시지 A, B 및 C
  • T3를 처리하기로 결정 - 클라이언트가 메시지 E 및 F를 수신합니다.
  • T4 - 스레드가 A, B 및 C를 처리 한 상태로 반환됩니다. 그러면 다른 스레드가 아직 수행하지 않은 경우 다음 배치를 선택할 수 있습니다.

생산자 이제 설정 방법 - DefaultJmsListenerContainerFactorySession.AUTO_ACKNOWLEDGE - 메시지가 그들이 스레드에 의해 선택되었는지의 여부, 즉시 전달 될 때 제거됩니다. 클라이언트가 T4 직전에 다운되면 메시지 A ~ F가 손실됩니다.

내가 T4 후)을 msg.acknowledge를 (호출하는 각 스레드를 생산자에 에게 Session.CLIENT_ACKNOWLEDGE를 사용을 계획했지만, documentation에 따라, 또한 어떤 될 것입니다, E와 F를 인정합니다 T4 이후에 클라이언트가 실패하면 손실됩니다.

트랜잭션 완료 세션이 처리 된 동안 만 메시지 A에서 F까지 처리하므로 트랜잭션 처리 세션이 도움이 될 것으로 확신하지는 않습니다.

내 목표는 고객의 실패의 경우에 대비하여 VM이 다운되면 스레드에 의해 성공적으로 처리되지 않은 모든 메시지가 주제/대기열에 남아 있습니다. 그런 다음 고객이 백업 할 때 픽업 할 수 있습니다.

어떻게하면이 아이디어를 얻을 수 있습니까?

S는

답변

0

내가 언급 할 첫 번째 것은 당신이 더 악화하고 잃게 속도를 증가 원인이 CLIENT_ACKNOWLEDGE를 사용하지 말아야한다는 것입니다. 클라이언트는 관련된 로컬 jms 세션의 모든 메시지를 승인하고 그렇지 않으면 하나의 배치에서 가져온 모든 메시지를 확인합니다.

메시지는 그들이 를 스레드에 의해 선택 여부

보통 인정이 onMessage 메소드 호출이 완료되면 다시 보낼 수 있습니다되었는지 여부, 즉시 전달 될 때 제거됩니다. 무슨 스레드가 있었 니? 처리가 동일한 스레드에서 수행되면 invokation으로 성공한 후에 만 ​​ack를 전송합니다.

어떻게 배치 소비를 달성 했습니까? u가 활성 mq 소비자 (http://activemq.apache.org/performance-tuning.html)를 의미하고 Spring (WS 또는 Integration) 및 AMQ 코드 기반에서 제공하는 것을 사용하고 있다면 적절한 구성에만 노력을 기울여야하고 99.999999 %의 성공률을 달성하기 위해 복잡한 사용자 정의 구현을하지 말아야합니다.모든 jms 중개인은 메시지를 잃거나 중복되어 0 등급을 잃지 않습니다. 그리고 대부분의 엔터프라이즈 시스템의 경우 1 만개의 메시지가 손실되거나 복제 된 경우가 일반적인 경우입니다.

어떻게 든 안정적인 전달을 얻으려면 어쨌든 지속적 전달 모드와 jms 트랜잭션을 사용해야합니다. 나를 위해 복제 된 메시지는 완전히 잃어버린 것보다 낫다. (실제로 모든 시스템 아키텍처는 그런 것들을 다루기 위해 멱등수를 쌓아야한다.) 그리고 말했듯이 AMQ 문서 배치는 안정성과 성능 사이의 균형입니다. 근본적으로 두 가지 속성을 동시에 달성 할 기회가 없습니다. 적어도 AMQ와 jms를 사용하십시오. 따라서 신뢰성이나 성능면에서 무엇이 더 중요한지 결정해야합니다. 가장 적절한 선택은 해당 트레이드 오프를 정의하고 메시지가 손실되거나 중복 될 경우 중복 된 메시지의 일괄 처리량을 허용할지 결정하는 것입니다.

+0

예, auto_ack은 onMessage()가 완료되면 수행됩니다. 현재이 메서드는 메시지를 컬렉션에 추가하기 만하면됩니다 (단순화하기 위해). 특정 조건이 충족되면 (시간, 콜렉션 크기 ...), 스레드는 콜렉션 내에서 메시지의 일부를 처리 할 시간이라고 결정합니다. 이것은 auto_ack에서 msg ack와 실제 처리 사이에 약간의 시간이있을 수 있음을 의미합니다. 어쩌면 제가 한 일은 실현 가능하지 않을 수도 있습니다. 그리고 여러분이 말했듯이, 최소한 잃을 여유가있는 msg의 최대 개수를 담을 수 있도록 컬렉션의 크기를 구성해야합니다. –

+0

이 경우 실제로 mapdb 또는 smth와 같은 일부 영구 데이터 구조를 사용할 수 있습니다. 메시지가 일부 내부 채널로 전송 된 순간부터이 메시지가 더 이상 전송 된 후에는 사용자의 책임입니다. 브로커가이 작업을 수행하려고하면 복잡한 논리가 필요 없게됩니다. 하지만 나에게 있어서도 mapdb는 오버 헤드처럼 보일 뿐이며, 나는 당신의 경우에 훌륭한 아키텍처라고 의심한다. 저의 관점에서 볼 때 가장 좋은 옵션은 메시지의 일부 낮은 %를 잃거나 중복 될 수 있고 적절한 창 크기를 설정할 수 있다는 것입니다 –