消息的生产者不会将消息作为持久性发送,当我尝试通过MessageListener消费消息时,如果发生任何异常(运行时),它将重试特定次数(默认值为AMQ的6)和消息迷路了。
原因是,由于生产者未将交付模式设置为持久性,因此在经过一定次数的重试尝试后,不会创建DLQ,并且消息不会移至DLQ。因此,我丢失了信息。
我的代码是这样的: -
@Configuration
@PropertySource("classpath:application.properties")
public class ActiveMqJmsConfig {
@Autowired
private AbcMessageListener abcMessageListener;
public DefaultMessageListenerContainer purchaseMsgListenerforAMQ(
@Qualifier("AMQConnectionFactory") ConnectionFactory amqConFactory) {
LOG.info("Message listener for purchases from AMQ : Starting");
DefaultMessageListenerContainer defaultMessageListenerContainer =
new DefaultMessageListenerContainer();
defaultMessageListenerContainer.setConnectionFactory(amqConFactory);
defaultMessageListenerContainer.setMaxConcurrentConsumers(4);
defaultMessageListenerContainer
.setDestinationName(purchaseReceivingQueueName);
defaultMessageListenerContainer
.setMessageListener(abcMessageListener);
defaultMessageListenerContainer.setSessionTransacted(true);
return defaultMessageListenerContainer;
}
@Bean
@Qualifier(value = "AMQConnectionFactory")
public ConnectionFactory activeMQConnectionFactory() {
ActiveMQConnectionFactory amqConnectionFactory =
new ActiveMQConnectionFactory();
amqConnectionFactory
.setBrokerURL(System.getProperty(tcp://localhost:61616));
amqConnectionFactory
.setUserName(System.getProperty(admin));
amqConnectionFactory
.setPassword(System.getProperty(admin));
return amqConnectionFactory;
}
}
@Component
public class AbcMessageListener implements MessageListener {
@Override
public void onMessage(Message msg) {
//CODE implementation
}
}
问题: - 通过在连接级别设置client-id(Connection.setclientid(" String")),即使消息不是持久的,我们也可以订阅为持久订阅者。通过执行此操作,如果应用程序抛出运行时异常,则在执行一定次数的重试后,将为队列创建DLQ并将消息移动到DLQ。
但是在DefaultMessageListenerContainer中,连接不会暴露给客户端。我认为它是由Class本身维护的。
如何在DefaultMessageListenerContainer中实现持久订阅?
答案 0 :(得分:0)
您可以在容器上设置客户端ID:
/**
* Specify the JMS client ID for a shared Connection created and used
* by this container.
* <p>Note that client IDs need to be unique among all active Connections
* of the underlying JMS provider. Furthermore, a client ID can only be
* assigned if the original ConnectionFactory hasn't already assigned one.
* @see javax.jms.Connection#setClientID
* @see #setConnectionFactory
*/
public void setClientId(@Nullable String clientId) {
this.clientId = clientId;
}
和
/**
* Set the name of a durable subscription to create. This method switches
* to pub-sub domain mode and activates subscription durability as well.
* <p>The durable subscription name needs to be unique within this client's
* JMS client id. Default is the class name of the specified message listener.
* <p>Note: Only 1 concurrent consumer (which is the default of this
* message listener container) is allowed for each durable subscription,
* except for a shared durable subscription (which requires JMS 2.0).
* @see #setPubSubDomain
* @see #setSubscriptionDurable
* @see #setSubscriptionShared
* @see #setClientId
* @see #setMessageListener
*/
public void setDurableSubscriptionName(@Nullable String durableSubscriptionName) {
this.subscriptionName = durableSubscriptionName;
this.subscriptionDurable = (durableSubscriptionName != null);
}