关闭

activemq 消息消费失败之后如何重新消费

5278人阅读 评论(0) 收藏 举报
分类:

在不开启事物的情况下 采用的是应答模式4(ActiveMQSession.AUTO_ACKNOWLEDGE)消费一次 应答一次

这时候消费失败了,由于没有配置死亡队列,消息就不会被消费堆积在队列中,那么怎么才可以让消息再被消费呢?

由于项目中的应用场景,有个方案启动和停止的功能,项目启动启动监听,项目停止,停止监听

具体实现代码如下

public class MqService {

	private JmsTemplate jmsTemplate;

	private CachingConnectionFactory cachingProductConnectionFactory;

	private CachingConnectionFactory cachingConsumersConnectionFactory;

	private static final String ACTIVEMQQUEUE_OPTIMIZATION = "";// 性能优化参数
																// consumer.prefetchSize预加载消息
																// 20条
																// ?consumer.prefetchSize=20

	/**
	 * 发送消息
	 * 
	 * @param ryzhMessage
	 */
	public void send(final RyzhMessage ryzhMessage) {
		
		// 得到MQ工具类
		RyzhMqHolder hodler = mqHolders.get(ryzhMessage.getShcemeId());
		// 发送信息
		jmsTemplate.setConnectionFactory(cachingProductConnectionFactory);
		jmsTemplate.send(hodler.getDestination(), new MessageCreator() {
			public Message createMessage(Session session) throws JMSException {
				ObjectMessage objectMessage = session.createObjectMessage();
				objectMessage.setObject(ryzhMessage);
				return objectMessage;
			}
		});
	}

	/**
	 * 监听
	 * 
	 * @param schemeId
	 * @param receiver
	 */
	public void startListen(RyzhScheme scheme) {
		RyzhMqHolder holder = mqHolders.get(scheme.getSchemeId());
		try {
			if (holder == null) {
				RyzhConsumer consumer = (RyzhConsumer) SpringBeanUtils.getBean("ryzhConsumer");
				consumer.setScheme(scheme);
				logger.info("RyzhMqService-启动消息队列监听器 schemeId=" + scheme.getSchemeId());
				// 如果是为空
				holder = new RyzhMqHolder();
				// 得到整合方案的配置
				TRyzhFa tRyzhFa = ((RyzhConsumer) consumer).getScheme().getZhfa();
				// 得到消息队列配置的信息
				String xxdlJson = tRyzhFa.getXxdlpz();
				// json转map
				RyzhMqConfig ryzhMqConfig = JSON.parseObject(xxdlJson, RyzhMqConfig.class);
				// 设置方案ID
				holder.setSchemeId(scheme.getSchemeId());
				// 设置目的地
				ActiveMQQueue destination = new ActiveMQQueue(RyzhMqConfig.QUEUE_NAME + scheme.getSchemeId() + ACTIVEMQQUEUE_OPTIMIZATION);
				holder.setDestination(destination);
				// 创建监听器
				DefaultMessageListener listener = new DefaultMessageListener();
				// 给监听器设置消费者
				listener.setReceiver(consumer);
				// 将监听器保存在holder中
				holder.setListener(listener);
				// 创建监听容器
				DefaultMessageListenerContainer listenerContainer = new DefaultMessageListenerContainer();
				// 监听容器属性的配置
				listenerContainer.setConnectionFactory(cachingConsumersConnectionFactory);
				// 设置目的地
				listenerContainer.setDestination(destination);
				// 设置监听器
				listenerContainer.setMessageListener(listener);
				// 设置消费者集群数
				listenerContainer.setConcurrentConsumers(ryzhMqConfig.getConcurrentConsumers());
				// 设置监听队列还是主题 默认是队列
				listenerContainer.setPubSubDomain(RyzhMqConfig.PUBSUB_DOMAIN);
				listenerContainer.setPubSubNoLocal(false);
				// listenerContainer.setAcceptMessagesWhileStopping(true);
				// 设置应答模式 默认是4
				listenerContainer.setSessionAcknowledgeMode(RyzhMqConfig.SESSION_ACKNOWLEDGEMODE);
				// 设置是否启动事物 默认不开启
				listenerContainer.setSessionTransacted(RyzhMqConfig.SESSION_TRANSACTED);
				// 将监听容器保存在holder中
				holder.setListenerContainer(listenerContainer);
				// 将holder缓存在map中
				mqHolders.put(scheme.getSchemeId(), holder);
				// 初始化容器
				holder.getListenerContainer().initialize();
				// 启动监听
				holder.getListenerContainer().start();
				logger.info("RyzhMqService-消息队列监听器启动成功 schemeId=" + scheme.getSchemeId());
			}
		} catch (Exception e) {
			logger.error("RyzhMqService-消息队列监听器启动失败 schemeId=" + scheme.getSchemeId(), e);
		}
	}

	public void stopListen(RyzhScheme scheme) {
		RyzhMqHolder ryzhMqHolder = mqHolders.get(scheme.getSchemeId());
		// 停止监听
		ryzhMqHolder.getListenerContainer().destroy();
		// 移除缓存
		mqHolders.remove(scheme.getSchemeId());
	}

	/**
	 * 取得MQHolder
	 * 
	 * @param ryzhMessage
	 * @return
	 */

	public Map<String, RyzhMqHolder> getMqHolders() {
		return mqHolders;
	}

	public void setMqHolders(Map<String, RyzhMqHolder> mqHolders) {
		this.mqHolders = mqHolders;
	}

	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	public CachingConnectionFactory getCachingProductConnectionFactory() {
		return cachingProductConnectionFactory;
	}

	public void setCachingProductConnectionFactory(CachingConnectionFactory cachingProductConnectionFactory) {
		this.cachingProductConnectionFactory = cachingProductConnectionFactory;
	}

	public CachingConnectionFactory getCachingConsumersConnectionFactory() {
		return cachingConsumersConnectionFactory;
	}

	public void setCachingConsumersConnectionFactory(CachingConnectionFactory cachingConsumersConnectionFactory) {
		this.cachingConsumersConnectionFactory = cachingConsumersConnectionFactory;
	}

}

具体的xml配置如下


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xmlns:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="
	   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
	default-autowire="byName">

	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<property name="connectionFactory" ref="cachingProductConnectionFactory"></property>
		<!-- 持久化 -->
		<property name="deliveryMode" value="2"></property>
		<!-- 不开启事物 -->
		<property name="sessionTransacted" value="false"></property>
		<!-- 应答模式是 INDIVIDUAL_ACKNOWLEDGE -->
		<property name="sessionAcknowledgeMode" value="4"></property>
	</bean>

	<bean id="ryzhMqService" class="com.dragonsoft.rygl.mq.RyzhMqService"
		scope="singleton">
		<property name="cachingConsumersConnectionFactory" ref="cachingConsumersConnectionFactory"></property>
		<property name="cachingProductConnectionFactory" ref="cachingProductConnectionFactory"></property>
		<property name="jmsTemplate" ref="jmsTemplate" />
	</bean>

	<bean id="defaultRyzhProduceProcessor"
		class="com.dragonsoft.rygl.ryzh.service.produce.DefaultRyzhProduceProcessor"
		scope="prototype">
		<property name="mgService" ref="ryzhMqService"></property>
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
		<property name="ip" value="${jmx.ip}"></property>
		<property name="port" value="${jmx.port}"></property>
		<property name="dataSourceManager" ref="dataSourceManager"></property>
	</bean>
	<!-- 生产者专用缓存池 -->
	<bean id="cachingProductConnectionFactory"
		class="org.springframework.jms.connection.CachingConnectionFactory">
		<property name="targetConnectionFactory" ref="connectionFactory"></property>
		<property name="reconnectOnException" value="true"></property>
		<property name="sessionCacheSize" value="${jms.sessionCacheSize}"></property>
	</bean>
	<!-- 消费者专用缓存池 -->
	<bean id="cachingConsumersConnectionFactory"
		class="org.springframework.jms.connection.CachingConnectionFactory">
		<property name="targetConnectionFactory" ref="connectionFactory"></property>
		<property name="reconnectOnException" value="true"></property>
		<property name="sessionCacheSize" value="${jms.sessionCacheSize}"></property>
		<span style="color:#ff0000;"><property name="cacheConsumers" value="false"></property>
		<property name="cacheProducers" value="false"></property></span>
	</bean>
	<bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
		<property name="brokerURL" value="${jms.brokerURL}" />
		<property name="userName" value="${jms.userName}"></property>
		<property name="password" value="${jms.password}"></property>
		<property name="useAsyncSend" value="${jms.useAsyncSend}"></property>
<span style="white-space:pre">		</span><!--
		<property name="redeliveryPolicy" >
			<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
				<property name="useExponentialBackOff" value="true"/>
				<property name="maximumRedeliveries" value="5"/><!-- 重发次数 5次 -->
				<property name="initialRedeliveryDelay" value="100"/><!-- 重发间隔时间100毫秒 -->
				<property name="backOffMultiplier" value="2.0"/>
			</bean>
		</property><pre name="code" class="html"><span style="white-space:pre">		</span>-->
</bean></beans>



注意红色部分,需要缓存,否则监听会被缓存无法stop。

以下就可以达到不用配置死信队列就可以重新消费信息。(其实原理就是重启了监听容器)


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:39327次
    • 积分:929
    • 等级:
    • 排名:千里之外
    • 原创:54篇
    • 转载:5篇
    • 译文:0篇
    • 评论:1条
    最新评论