Можно ли навести порядок сообщений в темах ActiveMQ, используя Spring Boot и JmsTemplate? - PullRequest
0 голосов
/ 03 апреля 2019

Играя с Spring Boot, ActiveMQ и JmsTemplate, я заметил, что кажется, что порядок сообщений не всегда сохраняется.При чтении ActiveMQ «Группы сообщений» предлагаются в качестве потенциального решения для сохранения порядка сообщений при отправке в тему.Есть ли способ сделать это с помощью JmsTemplate?

Добавить Примечание. Я начинаю думать, что JmsTemplate хорош для «запуска», но имеет слишком много проблем.

Пример кода ивывод консоли представлен ниже ...

@RestController
public class EmptyControllerSB {

    @Autowired
    MsgSender msgSender;

    @RequestMapping(method = RequestMethod.GET, value = { "/v1/msgqueue" })
    public String getAccount() {
        msgSender.sendJmsMessageA();
        msgSender.sendJmsMessageB();
        return "Do nothing...successfully!";
    }
}

@Component
public class MsgSender {

    @Autowired
    JmsTemplate jmsTemplate;

    void sendJmsMessageA() {
        jmsTemplate.convertAndSend(new ActiveMQTopic("VirtualTopic.TEST-TOPIC"), "message A");
    }

    void sendJmsMessageB() {
        jmsTemplate.convertAndSend(new ActiveMQTopic("VirtualTopic.TEST-TOPIC"), "message B");
    }
}

@Component
public class MsgReceiver {

    private final String consumerOne = "Consumer.myConsumer1.VirtualTopic.TEST-TOPIC";
    private final String consumerTwo = "Consumer.myConsumer2.VirtualTopic.TEST-TOPIC";

    @JmsListener(destination = consumerOne )
    public void receiveMessage1(String strMessage) {
        System.out.println("Received on #1a -> " + strMessage);
    }

    @JmsListener(destination = consumerOne )
    public void receiveMessage2(String strMessage) {
        System.out.println("Received on #1b -> " + strMessage);
    }

    @JmsListener(destination = consumerTwo )
    public void receiveMessage3(String strMessage) {
        System.out.println("Received on #2 -> " + strMessage);
    }
}

Вот вывод консоли (обратите внимание на порядок вывода в первой последовательности) ...

\Intel\Intel(R) Management Engine Components\DAL;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\gnupg\bin;C:\Users\LesR\AppData\Local\Microsoft\WindowsApps;c:\Gradle\gradle-5.0\bin;;C:\Program Files\JetBrains\IntelliJ IDEA 2018.3\bin;;.]
2019-04-03 09:23:08.408  INFO 13936 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-04-03 09:23:08.408  INFO 13936 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 672 ms
2019-04-03 09:23:08.705  INFO 13936 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-04-03 09:23:08.845  INFO 13936 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-04-03 09:23:08.877  INFO 13936 --- [           main] mil.navy.msgqueue.MsgqueueApplication    : Started MsgqueueApplication in 1.391 seconds (JVM running for 1.857)
2019-04-03 09:23:14.949  INFO 13936 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-04-03 09:23:14.949  INFO 13936 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-04-03 09:23:14.952  INFO 13936 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
Received on #2 -> message A
Received on #1a -> message B
Received on #1b -> message A
Received on #2 -> message B

<HIT DO-NOTHING ENDPOINT AGAIN>
Received on #1b -> message A
Received on #2 -> message A
Received on #1a -> message B
Received on #2 -> message B

1 Ответ

0 голосов
/ 08 апреля 2019

BLUF - Добавьте «? Consumer.exclusive = true» в объявление назначения для аннотации JmsListener.

Похоже, что решение не такое сложное, особенно если отказаться от «групп сообщений» ActiveMQ в пользу «эксклюзивных потребителей». Недостатком «групп сообщений» является то, что отправитель должен заранее знать о потенциальном разделении потребителей сообщений. Если производитель обладает этими знаниями, «группы сообщений» являются хорошим решением, так как решение в некоторой степени не зависит от потребителя.

Но подобное решение может быть реализовано со стороны потребителя, если потребителю объявить «исключительного потребителя» в очереди. Хотя я не видел в реализации JmsTemplate ничего, что непосредственно поддерживает это, похоже, что реализация Spring JmsTemplate передает имя очереди в ActiveMQ, а затем ActiveMQ «делает правильные вещи» и обеспечивает исключительное поведение потребителя.

Итак ...

Изменить следующее ...

private final String consumerOne = "Consumer.myConsumer1.VirtualTopic.TEST-TOPIC";

до ...

private final String consumerOne = "Consumer.myConsumer1.VirtualTopic.TEST-TOPIC";?consumer.exclusive=true

Как только я это сделал, был вызван только один из двух объявленных методов получения, и порядок сообщений поддерживался во всех моих тестовых прогонах.

...