Activemq队列已满向消息发送端发送通知

本文介绍了在使用Activemq进行request-reply模式的消息通知时,如何在队列满的情况下向消息生产者发送通知。作者通过配置applicationContext.xml,编写AMQClient消息生产者和MBeanChecker队列监控工具类,实现了这一功能,以确保及时响应用户避免延误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近公司准备用Activemq进行消息的通知,并且是request-reply模式的,遇到一个问题:在生产者向队列发送消息的时候,如果队列满了,则需要向生产者发送一个消息通知,从而尽快给用户一个答复,免得耽误时间,由于本人从未接触过Activemq,只能一边学习,一边实践了。今天终于做出来了,将重要代码贴在此地,以免忘记。

applicationContext.xml的内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
						http://www.springframework.org/schema/context
						http://www.springframework.org/schema/context/spring-context-2.5.xsd">


	<context:annotation-config />
	<context:component-scan base-package="****.******.***" />


	<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
		<property name="queuePrefetch" value="1" />
	</bean>


	<!-- get ConnectionFctory from URI:tcp://localhost:61616 -->
	<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<constructor-arg value="tcp://localhost:61616" />
		<property name="alwaysSyncSend" value="true" />
		<property name="producerWindowSize" value="0" />
		<property name="prefetchPolicy" ref="prefetchPolicy" />
	</bean>


	<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
		destroy-method="stop">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="maxConnections" value="10" />
		<property name="maximumActiveSessionPerConnection" value="10" />
		<property name="expiryTimeout" value="10" />
		<property name="idleTimeout" value="0" />
<!-- 		<property name="timeBetweenExpirationCheckMillis" value="50" /> -->
	</bean>


	<bean id="classPathResource" class="org.springframework.core.io.ClassPathResource">
		<constructor-arg value="activemq.xml" />
	</bean>


	<bean id="brokerFactory" class="org.apache.activemq.xbean.BrokerFactoryBean">
		<constructor-arg ref="classPathResource" />
		<property name="start" value="true" />
	</bean>


	<!-- queue for module demo -->
	<bean id="queueDm" class="org.apache.activemq.command.ActiveMQQueue">
		<property name="physicalName" value="queueDm" />
	</bean>
	<!-- N多 -->


<!-- 	<bean id="amqServer1" class="****.******.****.demo.amq.AMQServer" destroy-method="stop"> -->
<!-- 		<constructor-arg index="0" ref="pooledConnectionFactory" />connection factory -->
<!-- 		<constructor-arg index="1" ref="queueDm" />queue -->
<!-- 		<constructor-arg index="2" value="20" />thread core pool size -->
<!-- 		<constructor-arg index="3" value="30000" />thread pool thread keep alive time -->
<!-- 		<constructor-arg index="4" value="30" />concurrent task number -->
<!-- 	</bean> -->


	<bean id="amqClient" class="****.******.****.demo.amq.AMQClient" scope="prototype">
		<property name="pooledConnectionFactory" ref="pooledConnectionFactory" />
		<property name="adminQueue" ref="queueDm" />
	</bean>
	<bean id="mbeanchecker" class="test.****.******.****.demo.amq.MBeanChecker" />
	<bean id="messagesender" class="test.****.******.****.demo.amq.MessageSender">
		<property name="client" ref="amqClient" />
	</bean>
	
</beans>

activemq.xml配置文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
						http://activemq.apache.org/schema/core
						http://activemq.apache.org/schema/core/activemq-core.xsd">
	<!-- 定义了一个Broker,就是一个ActiveMQ的实例 -->
	<amq:broker brokerName="demoBroker"
		xmlns="http://activemq.apache.org/schema/core" useJmx="true"
		persistent="false">
		<amq:managementContext>
			<amq:managementContext connectorPort="6161"
				jmxDomainName="demoBrokerContext" connectorPath="/jmxrmi" />
		</amq:managementContext>

		<amq:systemUsage>
			<amq:systemUsage sendFailIfNoSpace="true">
				<amq:tempUsage>
					<amq:tempUsage limit="0kb" />
				</amq:tempUsage>
				<amq:memoryUsage>
					<amq:memoryUsage limit="10kb" />
				</amq:memoryUsage>
				<amq:storeUsage>
					<amq:storeUsage limit="0kb" />
				</amq:storeUsage>
			</amq:systemUsage>
		</amq:systemUsage>

		<amq:destinationPolicy>
			<amq:policyMap>
				<amq:policyEntries>
					<amq:policyEntry queue="queueDm" useCache="false"
						memoryLimit="10kb" producerFlowControl="true">
						<amq:pendingQueuePolicy>
							<amq:vmQueueCursor />
						</amq:pendingQueuePolicy>
					</amq:policyEntry>
				</amq:policyEntries>
			</amq:policyMap>
		</amq:destinationPolicy>

		<amq:transportConnectors>
			<transportConnector uri="tcp://localhost:61616" />
		</amq:transportConnectors>
	</amq:broker>
</beans>


消息生产者AMQClient.java代码:


package ****.******.****.demo.amq;

import java.util.Date;
import java.util.UUID;

import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.jms.pool.PooledSession;
import org.apache.activemq.pool.PooledConnection;
import org.apache.activemq.pool.PooledConnectionFactory;

public class AMQClient implements MessageListener {
	
	private PooledConnectionFactory pooledConnectionFactory;
	
	public PooledConnectionFactory getPooledConnectionFactory() {
		return pooledConnectionFactory;
	}

	public void setPooledConnectionFactory(
			PooledConnectionFactory pooledConnectionFactory) {
		this.pooledConnectionFactory = pooledConnectionFactory;
	}

	private ActiveMQQueue adminQueue;
	private MessageProducer producer;
	private MessageConsumer consumer;
	private Destination tempDest;
	
	public ActiveMQQueue getAdminQueue() {
		return adminQueue;
	}

	public void setAdminQueue(ActiveMQQueue adminQueue) {
		this.adminQueue = adminQueue;
	}

	private PooledConnection pConnection;
	private PooledSession pSession;
	
	public void start() throws JMSException {
		
		pConnection = (PooledConnection) pooledConnectionFactory.createConnection();
		pConnection.start();
		pSession = (PooledSession) pConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		producer = pSession.createProducer(adminQueue);
		producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
		tempDest = pSession.createTemporaryQueue();
		consumer = pSession.createConsumer(tempDest);
		consumer.setMessageListener(this);
		
	}

	public void stop() throws JMSException {
		producer.close();
		consumer.close();
		pSession.close();
		pConnection.close();
	}
	
	public void request(String request) throws JMSException {
		start();
		
		System.out.println("Requesting: " + request);
		ObjectMessage objectMessage = pSession.createObjectMessage();
		objectMessage.setObject(request);

		objectMessage.setJMSReplyTo(tempDest);
		objectMessage.setJMSTimestamp(new Date().getTime());
		String correlationId = UUID.randomUUID().toString();
		objectMessage.setJMSCorrelationID(correlationId);
		producer.send(objectMessage);
	}

	@Override
	public void onMessage(Message message) {
		try {
			System.out.println(((ObjectMessage)message).getObject());
		} catch (JMSException e) {
			System.out.println(e.getMessage());
		}
	}
}


查看队列信息的工具类:MBeanChecker.java


package test.****.******.****.demo.amq;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.QueueViewMBean;

public class MBeanChecker {
	
	public MBeanChecker() {
		new Thread() {
			public void run() {
				try {
					Thread.sleep(20000);
					for (int i = 0; i < 10000; i++) {
						Thread.sleep(1200);
						check();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}; 
		}.start();
	}
	
	private void check() throws Exception {
		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:6161/jmxrmi");
		JMXConnector connector = JMXConnectorFactory.connect(url, null);
		connector.connect();
		MBeanServerConnection connection = connector.getMBeanServerConnection();
		// 需要注意的是,这里的my-broker必须和定义broker的时候的名称相同
		/**
		 * org.apache.activemq:BrokerName=localhost,Type=Broker
		 * 中的BrokerName与Type必须首字小写
		 * org.apache.activemq:brokerName=localhost,type=Broker 大写小敏感。。
		 */
		ObjectName name = new ObjectName("demoBrokerContext:brokerName=demoBroker,type=Broker");
		BrokerViewMBean mBean = (BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
		System.out.println(mBean.getBrokerName());
		for (ObjectName queueName : mBean.getQueues()) {
			QueueViewMBean queueMBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, queueName, QueueViewMBean.class, true);
			System.out.println("\n------------------------------\n");
			// States for queue
			System.out.println("消息队列名称: --- " + queueMBean.getName());
			// Size
			System.out.println("队列中剩余的消息数目: --- " + queueMBean.getQueueSize());
			// Number of consumers:
			System.out.println("消费者数目: --- " + queueMBean.getConsumerCount());
			// Number of dequeue:
			System.out.println("出队列数目: ---" + queueMBean.getDequeueCount());
		}
	}
	
	public static void main(String[] args) {
		
	}
}

测试发送消息的类:MessageSender.java


package test.****.******.****.demo.amq;

import javax.jms.JMSException;

import org.springframework.web.context.ContextLoader;

import ****.******.****.demo.amq.AMQClient;

public class MessageSender {
	
	private AMQClient client;
	
	public AMQClient getClient() {
		return client;
	}

	public void setClient(AMQClient client) {
		this.client = client;
	}

	public MessageSender() {
		new Thread() {
			public void run() {
				try {
					Thread.sleep(20000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				sendRequest();
			};
		}.start();
	}
	
	private void sendRequest() {
		for (int i = 0; i < 5000; i++) {
			try {
				Thread.sleep(200);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			try {
				AMQClient client = (AMQClient) ContextLoader.getCurrentWebApplicationContext().getBean("amqClient");
				client.request("TEST-REQUEST:" + i);
				System.out.println("测试端发送消息: TEST-REQUEST:" + i);
			} catch (JMSException e) {
				System.err.println("jzf的发送端获取到的错误信息====================================" + e.getMessage());
				break;
			}
		}
	}
	
	public static void main(String[] args) {
		
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值