首页 > 解决方案 > 无法在主题中创建持久订阅者

问题描述

参考Link,我使用 JMS+ActiveMQ+SpringBoot 创建了持久订阅者。我还使用UUID.randomUUID().toString()生成了唯一客户端 ID 。但是,在启动订阅者(接收者)时,应用程序会抛出以下警告消息

Cause: Durable consumer is in use for client: 8f1019fd-50d4-457b-b417-2058917ed7bb and subscriptionName: org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter


请帮我删除上述警告信息。

在 ActiveMQ 服务器中创建具有客户端 ID 的持久主题 - '8f1019fd-50d4-457b-b417-2058917ed7bb' 在此处输入图像描述 以下是源代码

ReceiverTopicApplicaton.java

@SpringBootApplication
@EnableJms
public class ReceiverTopicApplicaton {
public static void main(String[] args) {
        SpringApplication.run(ReceiverTopicApplicaton.class, args);
    }


    private ConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory("tcp://localhost:61616");
    }

    @Bean
    public DefaultJmsListenerContainerFactory topicListenerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        //we need to set destinationResolver() to remove the warning message
        factory.setDestinationResolver(destinationResolver());
        factory.setPubSubDomain(true); 
        factory.setSubscriptionDurable(true);
        factory.setConcurrency("3-10");
        factory.setClientId(UUID.randomUUID().toString());
        factory.setSubscriptionDurable(true);
        return factory;
    }

接收器.java

@Component
public class Receiver {

    @JmsListener(destination = "durable.topic", containerFactory = "topicListenerFactory")
    public void receiveMessage(final Message message) throws JMSException {
        if (message instanceof ObjectMessage) {
            Object object = ((ObjectMessage) message).getObject();
            StudentDto studentDto = (StudentDto) object;
            System.out.println("Receiver :: Student Object Received..." + studentDto);
        }
    }

}

StudentDto.java

public class StudentDto implements Serializable {

    private Long studentId; 
    private String studentName; 
    private String gender;
    private Long age;   
    private String studentClass;    
    private LocalDate birthDate;

    public StudentDto() {}

    public StudentDto(Long studentId, String studentName,String gender,Long age,String studentClass, LocalDate birthDate) {
        this.studentId = studentId;
        this.studentName = studentName;
        this.gender = gender;
        this.age = age;
        this.studentClass = studentClass;
        this.birthDate = birthDate;
    }

    @Override
    public String toString() {
        return "Student [studentId=" + studentId + ", studentName=" + studentName + ", Gender=" + gender + ", Age="
                + age + ", studentClass=" + studentClass + ", birthDate=" + birthDate + "]";
    }
}

发送消息应用程序.java

@SpringBootApplication
@EnableJms
public class SendMessageApplication {

    public static void main(String[] args) {
        SpringApplication.run(SendMessageApplication.class, args);
    }

    @Bean
    public JmsListenerContainerFactory<?> topicListenerFactory(
            ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer)       
    {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setPubSubDomain(true); 
        return factory;
    }

TopicSendMessage.java

@RestController
@RequestMapping(path = "/schoolDashboard/topic")
class TopicSendMessage {

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping(path = "/publishMessage")
    public void sendMessage() throws Exception{
        String birthDate = "1978-10-05";
        StudentDto studentDto = new StudentDto(new Long(1), "Ritesh", "Male", new Long(12), "Class-V", LocalDate.parse(birthDate));
        System.out.println("TopicSendMessage.java :: Topic - Publishing Student Object....");               
        jmsTemplate.setPubSubDomain(true);
        jmsTemplate.convertAndSend("student.topic", studentDto);
    }
}

标签: spring-bootactivemqjms-topic

解决方案


由于您使用的是 ActiveMQ 5.x,因此您使用的是 JMS 1.1,而 JMS 1.1 规范规定只能有一个订阅者附加到持久订阅。由于您使用setConcurrency("3-10")的是 Spring 尝试在同一个持久订阅上创建多个订阅者,这会导致您看到的错误。您应该:

  • 使用setConcurrency("1"). 这可能会导致性能显着下降。
  • 移动到支持 JMS 2.0 的代理(如ActiveMQ Artemis )并调用setSubscriptionShared(true),因为 JMS 2.0 没有与 JMS 1.1 相同的关于持久订阅的多个订阅者的限制。

推荐阅读