在 ActiveMQ Artemis 控制台上看不到 Pub/Sub 消息

Cannot see Pub/Sub message on ActiveMQ Artemis console

提问人:CoderJammer 提问时间:10/17/2023 最后编辑:CoderJammer 更新时间:10/17/2023 访问量:58

问:

我正在使用 Felipe Gutierrez (2017) 的 Spring Boot Messaging 一书学习 JMS。

它说明了有关消息驱动编程的几种模式,但是,到达代理时,它解释了使用 Apache ActiveMQ 的 Java / Spring Boot 消息传递。

它说解释的代码将与任何其他代理一起使用,所以我安装了 ActiveMQ Artemis。

我有一个非常简单的源代码,配置

@Configuration
public class JmsConfig {

  @Bean
  public MessageConverter jacksonJmsMessageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver
    return converter;
  }
}

a Sender 类:

@Component
public class Sender  {

  private final JmsTemplate jmsTemplate;

  public Sender(JmsTemplate jmsTemplate){
    this.jmsTemplate = jmsTemplate;
  }

  public void sendMessage(String destination, String message){
    this.jmsTemplate.convertAndSend("test-destination", message);
  } 
}

和一个接收器

....
@JmsListener(destination = "test-destinaton")
public void consumeTopicOne(String message) {
  log.info("Received Message Queue/Topic1: " + message);
}
....

文件如下:application.properties

spring.artemis.mode=native
spring.artemis.embedded.enabled=false
spring.artemis.broker-url=tcp://localhost:61616
spring.artemis.user=admin
spring.artemis.password=admin

spring.jms.pub-sub-domain=false

注意:主类没有注解。@EnableJms

现在,我设法使用“点对点”模式(队列)发送消息,并在我的控制台中看到它,只要我注释掉接收器

enter image description here

如果我单击消息计数,我可以看到文本(还有其他选项)。但是,如果我尝试切换到 Publisher/Subscriber 方法,请设置以下属性(根据本书):

spring.jms.pub-sub-domain=true

应用程序运行良好,消息将被发送和接收,但我无法在控制台上看到它!即使我注释掉了接收者(就像我对队列所做的那样),我仍然看不到发送的消息。

因此,谈到队列:为什么我只有在尚未收到消息时才看到消息?拥有已发送消息的历史记录可能很有用。

谈到 Pub/Sub:为什么无论消息是否被消费,我都看不到任何内容?

关于这本书..也许我必须改变它?


感谢您的所有回复。

我查看了 @justin-bertram 发布给我的讨论,我读到:

由于您正在向 JMS 主题发送消息,因此您将受到主题 发布/订阅语义。发布/订阅语义决定 消息仅放置在有效的订阅中。当您的 订阅者处于脱机状态,它在代理上没有有效的订阅 接收消息,因此它将错过发送给它的消息 当它处于离线状态时。

您可以使用持久订阅者在 订阅者处于离线状态

这不是有效的订阅吗:

@JmsListener(destination = "test-destinaton")
public void consumeTopicOne(String message) {
   log.info("Received Message Queue/Topic1: " + message);
}

这个例子直接取自这本书,我发现其他的例子非常清楚,与我的非常相似,例如这里

我将尝试使用客户端服务器架构,但似乎很奇怪,我不能将(例如目的)发布者和订阅者放在同一个项目中。

java spring-boot jms activemq-artemis messagebroker

评论

1赞 Justin Bertram 10/17/2023
您看到的是预期的行为。请参阅相关问题 此处 和 此处此处.
1赞 Justin Bertram 10/18/2023
如果您的订阅者处于活动状态,那么当消息发送到主题时,它将立即被分派给订阅者并被使用,这意味着您将不会在代理的 Web 控制台上看到它。如果禁用订阅者,就像禁用队列一样,那么将根据 JMS 主题(即发布/订阅)语义简单地丢弃消息。因此,无论哪种方式,您都无法通过经纪人的 Web 控制台看到消息,除非您配置了像 Domenico 在他的回答中提到的非排他性转移之类的东西。同样,据我所知,您看到的是预期的行为。

答:

2赞 Domenico Francesco Bruscino 10/17/2023 #1

该属性配置 JmsTemplate 和 JmsMessageListenerContainer 的工作方式,请参阅文档spring.jms.pub-sub-domain

当目标是 JMS 队列时,因此可以随时接收任何已发送的消息。spring.jms.pub-sub-domain= false

当目标是 JMS 主题时,因此任何已发送的消息只能从当前订阅者接收。这就解释了为什么如果没有订阅者,您不会在控制台上看到这些消息。spring.jms.pub-sub-domain= true

当客户端接收到消息时,该消息将从服务器队列中删除。您可以使用非独占转移在收到邮件时将邮件的副本发送到另一个地址。